awk和sed的新手,我怎么能改进这个?多个sed和awk命令

时间:2013-12-15 04:46:13

标签: bash sed awk xxd

这是我构建的脚本

  • 根据作为参数提供的扩展名,它需要一个文件列表。

  • 然后删除模式00000000之前的所有内容:在这些文件中。

  • 模式00000000:前面是字符串<pre>,然后删除这五个第一个字符。
  • 然后脚本删除文件的最后三行
  • 脚本只输出文件的hexdump数据。
  • 脚本运行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

它也可以按照我的意愿行事,但我怀疑有些东西需要改进,但是唉,我是使用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:

2 个答案:

答案 0 :(得分:1)

虽然@CodeGnome是正确的,而且这可能属于Code Review SE,但无论如何你要去:

  1. 将多个sed命令组合成一个命令的效率稍高,例如:

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

    我决定收回这一部分,因为我不确定它是更好还是更清楚。您的版本没问题,只有s/^<pre>//优于s/^.....//

  2. 在检查发出错误信号的参数数量时使用exit 1

  3. 那里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 ""}'
    
  6. 看来你想学习。您可能也对这个其他答案感兴趣:What are the rules to write robust shell scripts?

答案 1 :(得分:0)

错误消息应该发送到stderr,不应该硬编码脚本的名称以防以后重命名,并且应该以非零值退出。

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

如果您要将then放在与if相同的行上,那么您应该将do放在与for相同的行上,为了保持一致性:

for file in *.$1; do

使用file作为全名,使用filename作为基本名称会让变量名称选择混乱。我会使用basename作为变量来匹配操作。你需要引用参数扩展:

    basename=$(basename "$file")

但是你不需要引用作业的右侧:

    extension=${basename##*.}

没有扩展名的文件名部分有时称为root(在vi和csh : - 修饰符中,您可以使用: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