簡體   English   中英

awk和sed的新手,我該如何改善呢? 多個sed和awk命令

[英]New to awk and sed, How could I improve this? Multiple sed and awk commands

這是我構建的腳本

  • 它根據作為參數提供的擴展名獲取文件列表。

  • 然后,它將刪除這些文件中模式00000000:之前的所有內容。

  • 模式00000000:前面是字符串<pre> ,然后刪除了<pre>五個字符。
  • 然后,腳本刪除文件的最后三行
  • 該腳本僅輸出文件的十六進制轉儲數據。
  • 該腳本運行xxd將hexdump轉換為file.jpg
if [[ $# -eq 0 ]] ; then
        echo 'Run script as ./hexconv ext'
        exit 0
    fi

    for file in *.$1
    do
        filename=$(basename $file)
        extension="${filename##*.}"
        filename="${filename%.*}"

        sed -n '/00000000:/,$p' $file | sed '1s/^.....//' | head -n -3 | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" "$10" "$11" "$12" "$13" "$14" "$15" "$16" "$17}' | xxd -p -r > $filename.jpg
    done

它也可以按我想要的方式工作,但是我懷疑有一些可以改進的地方,但是,a,我是awk和sed使用的新手。

摘錄自文件

<th>response-head:</th>
<td>HTTP/1.1 200 OK
Date: Sun, 15 Dec 2013 04:27:04 GMT
Server: PWS/8.0.18
X-Px: ms h0-s34.p6-lhr ( h0-s35.p6-lhr), ht-d h0-s35.p6-lhr.cdngp.net
Etag: &quot;4556354-9fbf8-4e40387aadfc0&quot;
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0
Accept-Ranges: bytes
Content-Length: 654328
Content-Type: image/jpeg
Last-Modified: Thu, 15 Aug 2013 21:55:19 GMT
Pragma: no-cache
</td>
  </tr>
</table>
<hr/>
<pre>00000000:  ff  d8  ff  e0  00  10  4a  46  49  46  00  01  01  01  00  48  ......JFIF.....H
00000010:  00  48  00  00  ff  e1  00  18  45  78  69  66  00  00  49  49  .H......Exif..II
00000020:  2a  00  08  00  00  00  00  00  00  00  00  00  00  00  ff  ed  *...............
00000030:  00  48  50  68  74  73  68  70  20  33  2e  30  00  .HPhotoshop 3.0.
00000040:  38  42  49  4d  04  04  00  00  00  00  00  1c  01  5a  00  8BIM..........Z.
00000050:  03  1b  25  47  1c  02  00  00  02  00  02  00  38  42  49  4d  ..%G........8BIM
00000060:  04  25  00  00  00  00  00  10  fc  e1  89  c8  b7  c9  78  .%.............x
00000070:    34  62  34  07  58  77  eb  ff  e1  03  a5  68  74  74  70  /4b4.Xw.....http
00000080:  3a    6e  73  2e  61  64  62  65  2e  63  6d  ://ns.adobe.com/
00000090:  78  61  70  31  2e  30  00  3c  78  70  61  63  6b  xap/1.0/.&lt;?xpack
000000a0:  65  74  20  62  65  67  69  6e  3d  22  ef  bb  bf  22  20  69  et begin="..." i
000000b0:  64  3d  22  57  35  4d  30  4d  70  43  65  68  69  48  7a  72  d="W5M0MpCehiHzr
000000c0:  65  53  7a  4e  54  63  7a  6b  63  39  64  22  3e  20  3c  eSzNTczkc9d"?&gt; &lt;
000000d0:  78  3a  78  6d  70  6d  65  74  61  20  78  6d  6c  6e  73  3a  x:xmpmeta xmlns:
000000e0:  78  3d  22  61  64  62  65  3a  6e  73  3a  6d  65  74  61  x="adobe:ns:meta
000000f0:    22  20  78  3a  78  6d  70  74  6b  3d  22  41  64  62  /" x:xmptk="Adob
00000100:  65  20  58  4d  50  20  43  72  65  20  35  2e  30  2d  63  e XMP Core 5.0-c
00000110:  30  36  31  20  36  34  2e  31  34  30  39  34  39  2c  20  32  061 64.140949, 2
00000120:  30  31  30  31  32  30  37  2d  31  30  3a  35  37  3a  010/12/07-10:57:

盡管@CodeGnome是正確的,並且這可能屬於Code Review SE ,但無論如何您都可以在這里進行:

  1. 將多個 sed命令組合成一個命令的效率 sed ,例如:

     sed -n -e 's/^<pre>//' -e '/00000000:/,$p' 

    我決定撤回這部分,因為我不確定這是更好還是更清晰。 您的版本很好,除了s/^<pre>//s/^.....//更好。

  2. 檢查參數數量以指示錯誤時,請使用exit 1

  3. for file in *.是什么for file in *. 那里? 迭代所有以點結尾的文件嗎? 錯字?

  4. 除非您100%確定文件名將永遠不包含空格,否則應使用引號,但不要在不需要的地方引號,例如:

     filename=$(basename "$file") # need to quote extension=${filename##*.} # no need, filename=${filename%.*} # no need sed ... "$file" # need to quote ... | xxd > "$filename".jpg # need to quote 
  5. 最后一個awk可能更短,並且循環出錯的可能性更低:

     ... | awk '{printf $2; for (i=3; i<=17; ++i) printf " " $i; print ""}' 

看來您想學習。 您可能也對另一個答案感興趣: 編寫健壯的Shell腳本的規則是什么?

錯誤消息應該發送到stderr,不要硬編碼腳本的名稱,以防日后重命名,並且應該以非零值退出。

if (( ! $# )); then
  echo >&2 "Run script as '$0' \$extension"
  exit 1
fi

如果你打算把then在同一行if ,那么你就應該把do在同一行for ,也為一致性:

for file in *.$1; do

使用file作為全名,使用filename作為基本filename會使變量名選擇混亂。 我將使用basename作為變量,以匹配操作。 並且您需要引用參數擴展:

    basename=$(basename "$file")

但是,您無需引用作業的右側:

    extension=${basename##*.}

文件名中不帶擴展名的部分有時稱為root (在vi和csh : -modifiers中,您可以通過:r獲得它)...使用該名稱比更改現有變量並重新使用它更容易混淆:

    root=${basename%.*}

至於實際的管道,我將對其重新排序以將head放在awk之前,因為sedhead都是關於要打印的行,並且應該在修改這些選定行的awk之前分組在一起。 我還將使用循環和printf使awk更加靈活:

    sed -n '/0\{8\}:/,$p' "$file" | 
      head -n -3 | 
      awk '{ printf "%s", $2; for (f=3;f<=17;++f) { printf " %s", $f }; print "" }' | 
      xxd -p -r > "$root.jpg"
done

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM