0

所有,我正在尝试运行一个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/

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

有任何想法吗?

4

2 回答 2

2

但我意识到,如果我的第一个替代品与模式不匹配,它会继续执行下一个命令。如果没有匹配,有没有办法让它退出?

您可以使用分支命令。我在适当的位置添加并评论了它们:

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

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
于 2012-09-24T20:03:01.743 回答
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命令之后添加。

于 2012-09-24T20:00:13.047 回答