Sed:从';s';命令

Sed:从';s';命令,sed,Sed,我正在试验sed,最近我注意到了一些有趣的行为。但是,我找不到任何描述它的文档 假设我们有一个名为“sedtest”的文件: $cat sedtest hello 0 world example 4 sed Phone number: 123-456-789 接下来,我将通过sed运行它: $cat sedtest | sed '/\([[:digit:]]\+\)/s,,(\1),' hello (0) world example (4) sed Phone number:

我正在试验sed,最近我注意到了一些有趣的行为。但是,我找不到任何描述它的文档

假设我们有一个名为“sedtest”的文件:

$cat sedtest
 hello 0 world
 example
 4 sed
 Phone number: 123-456-789
接下来,我将通过sed运行它:

$cat sedtest | sed '/\([[:digit:]]\+\)/s,,(\1),'
 hello (0) world
 example
 (4) sed
 Phone number: (123)-456-789
这相当容易理解sed脚本:

  • 首先,它通过regexp
    \([[:digit:]\+\)
    匹配字符串,这意味着“匹配包含1个或多个数字的字符串”。注意,我还使用了
    s
    -命令样式
    \(
    \)
    括号来标记这里的子字符串(允许吗?)
  • 在匹配的情况下,它继续执行
    s
    命令
    s,,(\1),
    (带有空的regexp字段),这意味着“将匹配的子字符串替换为
    (\1)
  • 起初我认为它应该会出错,因为
    \1
    和类似的反向引用应该只适用于
    s
    命令匹配器字段中的子字符串,在本例中该字段为空

    但结果就像是
    s,\([[:digit:]\+\),(\1),
    script(
    \regexp\
    matcher在
    s
    命令匹配器字段中移动)

    因此,问题是:从
    s//replace/
    命令反向引用由
    s/regexp/replace/
    规则匹配的文本的子字符串是否正常(即,这是期望的行为),就好像它们由
    s/regexp/replace/
    命令匹配一样

    p.S.

    我的sed版本是:GNU sed 4.2.1

    这个问题背后的动机是,你们可以这样做:

    sed'/^Number:\([[:digit:]\+\)$/{s,,#Number:(\1),;p;d};问题1’
    ,即

  • /^Number:\([[:digit:]\+\)$/
    -匹配每种类型的字符串
    编号:12345
    ,如果匹配:
    • s,,#编号:(\1),
      -将其替换为
      #编号:(12345)
    • p
      -打印它
    • d
      -清除模式空间,并开始新的循环(获取新行并从开头开始解析脚本表达式)
  • q 1
    -以代码1退出。仅当步骤1中未出现匹配时(由于
    d
    命令存在),才会执行此命令-它检查“不匹配”情况,在我的情况下,这意味着“不允许字符串”,并且必须导致错误

  • 这里的主要技巧是在替换发生后执行
    p
    d
    命令,这在使用“正常的”
    s/match/replace/
    命令时是不可能的。

    这是正常的。除非进行另一次匹配,否则不会清除后参考保留空间。由于
    s
    的正则表达式为空,
    \1
    引用该正则表达式之前的捕获组。您可以看到不同之处:

    $ sed '/\([[:digit:]]\+\)/s,\(a\),(\1),' sedtest
    hello 0 world
     example
     4 sed
     Phone number: 123-456-789
    
    不匹配(行中的数字也有
    a
    ,但后参考保留已清除

    $sed '/\([[:digit:]]\+\)/s,\(e\),(\1),'
    h(e)llo 0 world
     example
     4 s(e)d
     Phon(e) number: 123-456-789
    
    e
    匹配,并成为反向参考

    如果不希望出现这种行为,则不应首先在
    [[:digit:]
    周围放置
    \(\)
    来创建反向引用