4

假设您有一些这样的文本:

  foobar 42                  | ff 00 00 00 00
  foobaz 00                  | 0a 00 0b 00 00
  foobie 00                  | 00 00 00 00 00
  bar    00                  | ab ba 00 cd 00

并且你想改变所有非00在右手边的|要被包裹的(),但前提是在左手边的|00。期望的结果:

  foobar 42                  | ff 00 00 00 00
  foobaz 00                  | (0a) 00 (0b) 00 00
  foobie 00                  | 00 00 00 00 00
  bar    00                  | (ab) (ba) 00 (cd) 00

有没有使用 sed 解决这个问题的好方法,还是我试图超越语言的能力?

到目前为止,这是我的工作:

s/[^0]\{2\}/(&)/g包装您的 RHS 值

/[^|]*00[^|]*|/可以用作命令的地址以仅在有效行上操作

现在的诀窍是制定一个在模式空间的一部分中执行的命令。

这确实不是面向行的,这可以解释为什么我无法获得有效的表达式。

4

5 回答 5

4
$ awk 'BEGIN{ FS=OFS="|" } $1~/ 00 /{gsub(/[^ ][^0 ]|[^0 ][^ ]/,"(&)",$2)} 1' file
  foobar 42                  | ff 00 00 00 00
  foobaz 00                  | (0a) 00 (0b) 00 00
  foobie 00                  | 00 00 00 00 00
  bar    00                  | (ab) (ba) 00 (cd) 00

如果您要搜索的字符串变得比 2 0 更复杂,这是一种更通用的可扩展方法,因为它不需要您编写一个否定字符串的 RE:

$ awk '
    BEGIN{ FS=OFS="|" }
    $1 ~ / 00 /{
        split($2,a,/ /)
        $2=""
        for (i=2;i in a;i++)
            $2 = $2 " " (a[i] == "00" ? a[i] : "(" a[i] ")")
    }
    1
' file
  foobar 42                  | ff 00 00 00 00
  foobaz 00                  | (0a) 00 (0b) 00 00
  foobie 00                  | 00 00 00 00 00
  bar    00                  | (ab) (ba) 00 (cd) 00
于 2013-08-20T02:34:00.510 回答
3

这可能对您有用(GNU sed):

 sed -r '/^\s*\S+\s*00/!b;s/\b([^0][^0]|0[^0]|[^0]0)\b/(&)/g' file

这忽略不以单词开头后跟 00 的行。然后它插入圆括号 2 个既不是 0 也不是包含 0 和非 0 的字符串。

于 2013-08-20T07:28:44.107 回答
2

看来,(尽管我一直这样做)管道 sed 到 sed 到 sed 意味着我第一次没有做对:这是一个

sed -r '/00.*\|/  {   ## match lines with a zero before the pipe

    ### surround tailing digits with ()
    ##  
     s/(\w\w) (\w\w) (\w\w) (\w\w) (\w\w)$/(\1) (\2) (\3) (\4) (\5)/;  

    ### replace the zeroes (00) with 00
    ##
    s/\(00\)/00/g; 

}'  txt
  富吧 42 | ff 00 00 00 00
  美食家 00 | (0a) 00 (0b) 00 00
  傻瓜00 | 00 00 00 00 00
  酒吧00 | (ab) (ba) 00 (cd) 00

好的!

于 2013-08-20T05:54:57.947 回答
1

好吧试试这个!

$ sed '/00 *|/ { h; s/|.*/|/; x; s/.*|//; s/\(0[1-9a-f]\|[1-9a-f][0-9a-f]\)/(\1)/g; H; x; s/\n//; }' yourfile.txt

我得到的输出是这样的:

foobar 42                  | ff 00 00 00 00
foobaz 00                  | (0a) 00 (0b) 00 00
foobie 00                  | 00 00 00 00 00
bar    00                  | (ab) (ba) 00 (cd) 00

已编辑,因此00|.

于 2013-08-20T02:27:29.727 回答
1

我认为awk这可能是这项工作的更好工具,但可以通过以下方式完成sed

sed '/^[^ ]*  *00 *|/{
         :a
         s/\(|.*[^(]\)\([0-9a-f][1-9a-f]\)/\1(\2)/
         t a
         :b
         s/\(|.*[^(]\)\([1-9a-f][0-9a-f]\)/\1(\2)/
         t b
     }' data

该脚本查找包含00在管道之前的行,并且仅将操作应用于这些行。有两个替代操作,每个都包裹在一个循环中。和:a线:b是标签。如果自上次跳转后执行了替换,则t aandt b命令是到指定标签的条件跳转。这两个替换几乎是对称的;第一个处理任何不以 0 结尾的数字;第二个处理任何不以 0 开头的数字;他们之间,他们忽略了00。这些模式查找管道、任何不以左括号结尾的字符序列(以及适当的数字对;它替换了它,以便数字在括号内结束。循环是必要的,因为g修饰符不再从头开始,并且模式通过数字向后工作。

鉴于此数据文件(您的稍微扩展的版本):

foobar 42                  | ff 00 00 00 00
foobaz 00                  | 0a 00 0b 00 00
foobie 00                  | 00 00 00 00 00
bar    00                  | ab ba 00 cd 00
fizbie    00               | ab ba 00 cd 90
fizzbuzz    00             | ab ba 00 cd 09

脚本的输出是:

foobar 42                  | ff 00 00 00 00
foobaz 00                  | (0a) 00 (0b) 00 00
foobie 00                  | 00 00 00 00 00
bar    00                  | (ab) (ba) 00 (cd) 00
fizbie    00               | (ab) (ba) 00 (cd) (90)
fizzbuzz    00             | (ab) (ba) 00 (cd) (09)

在每个替换命令之后添加一个具有中等教育p意义的,因此您可以看到替换是如何工作的:

foobar 42                  | ff 00 00 00 00
foobaz 00                  | 0a 00 (0b) 00 00
foobaz 00                  | (0a) 00 (0b) 00 00
foobaz 00                  | (0a) 00 (0b) 00 00
foobie 00                  | 00 00 00 00 00
bar    00                  | ab ba 00 (cd) 00
bar    00                  | ab (ba) 00 (cd) 00
bar    00                  | (ab) (ba) 00 (cd) 00
bar    00                  | (ab) (ba) 00 (cd) 00
fizbie    00               | ab ba 00 (cd) 90
fizbie    00               | ab (ba) 00 (cd) 90
fizbie    00               | (ab) (ba) 00 (cd) 90
fizbie    00               | (ab) (ba) 00 (cd) (90)
fizbie    00               | (ab) (ba) 00 (cd) (90)
fizzbuzz    00             | ab ba 00 cd (09)
fizzbuzz    00             | ab ba 00 (cd) (09)
fizzbuzz    00             | ab (ba) 00 (cd) (09)
fizzbuzz    00             | (ab) (ba) 00 (cd) (09)
fizzbuzz    00             | (ab) (ba) 00 (cd) (09)
于 2013-08-20T02:56:28.473 回答