Sed - 如果模式不匹配,则停止多部分命令?

时间:2012-09-24 18:26:18

标签: sed

全部,我正在尝试运行sed命令从某些文件中删除卡号。我试图在一个单行中做这个,我认为一切进展顺利 - 但我意识到如果我的第一个替代品与模式不匹配,它会继续进入下一个命令。如果没有匹配,有没有办法让它退出?

我们的系统上有16-22个长度卡号,所以我写了一个可变长度。我的规格是保留任何16位数字的前6位和后4位,以及中间任何位置的斧头(星号)。

sed 'h;s/[0-9]\{6\}\([0-9]\{5\}\)\([0-9]*\)[0-9]\{4\}/\1\2/;s/./*/g;x;s/\([0-9]\{6\}\)[0-9]*\([0-9]\{4\}\)/\1\2/;G;s/\n//;s/\([0-9]\{6\}\)\([0-9]\{4\}\)\(.*\)/\1\3\2/'

问题在于如果命令的这一部分:

s/[0-9]\{6\}\([0-9]\{5\}\)\([0-9]*\)[0-9]\{4\}/\1\2/

什么都没找到,模式空间仍然是输入。它继续进入下一个命令,然后用星号替换所有内容。我最终得到的是输入后跟相同数量的星号(如果它与我的第一个替换中的“卡号资格”不匹配)。如果 被认为是可能的卡号,它就能完美运行。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

  

但我意识到,如果我的第一个替代品与它的模式不符   继续进入下一个命令。有没有办法让它退出if   没有比赛?

您可以使用分支命令。我添加并评论了它们:

sed '
    h;
    s/[0-9]\{6\}\([0-9]\{5\}\)\([0-9]*\)[0-9]\{4\}/\1\2/;

    ## If last substitution command succeeds, go to label "a".
    t a
    ## Begin next cycle (previous substitution command didn't succeed).
    b
    ## Label "a".
    :a

    s/./*/g;
    x;
    s/\([0-9]\{6\}\)[0-9]*\([0-9]\{4\}\)/\1\2/;
    G;
    s/\n//;
    s/\([0-9]\{6\}\)\([0-9]\{4\}\)\(.*\)/\1\3\2/
'

由于评论,

更新

所以你要转型

texttexttext111111222223333texttexttext

in

texttexttext111111*****3333texttexttext 

尝试:

echo "texttexttext111111222223333texttexttext" | 
sed -e '
    ## Add newlines characters between the characters to substitute with "*".
    s/\([0-9]\{6\}\)\([0-9]\{5\}\)\([0-9]*\)\([0-9]\{4\}\)/\1\n\2\3\n\4/;
    ## Label "a".
    :a; 
    ## Substitute first not-asterisk character between newlines with "*".
    s/\(\n\**\)[^\n]\(.*\n\)/\1*\2/; 
    ## If character before second newline is not an asterisk, repeat
    ## the substitution from label "a".
    /^.*\*\n/! ta; 
    ## Remove artificial newlines.
    s/\n//g
    ## Implicit print.
'

输出:

texttexttext111111*****3333texttexttext

答案 1 :(得分:1)

来自man sed

t label
      If  a  s///  has  done  a successful substitution since the last
      input line was read and since the last  t  or  T  command,  then
      branch to label; if label is omitted, branch to end of script.

T label
      If  no  s///  has  done a successful substitution since the last
      input line was read and since the last  t  or  T  command,  then
      branch  to  label; if label is omitted, branch to end of script.
      This is a GNU extension.

所以我认为您可以在第一个T;命令之后添加s