仅当行不包含关键字时才附加到匹配行

时间:2017-08-25 08:02:54

标签: bash shell

我有一个文件,我们称之为input.txt。它有很多行,但唯一相关的行包含模型语句;

height ~ mu gender

它也可能包含;

height !n ~ mu date_birth !r g

因此,在正则表达式中识别行的一致因素是^height.*~.*$。 至少这是我到目前为止所设计的。

我想仅在!r g已经存在的情况下才将!r g附加到结尾行。我尝试混合来自hereherehere的答案,但我无法弄明白。我更喜欢一个命令。我也一直在玩复杂的awksed,但我觉得这太简单了,对于有这个问题的人来说,这并不是一件非常困难的事情。经验。

期望的结果:

如果height ~ mu genderheight ~ mu gender !r g

如果height !bin ~ mu date_birth !r g则不需要发生任何事情。

如果height !bin ~ mu genderheight !bin ~ mu gender !r g

修改

到目前为止,我试过了;

如果sed '/^height.*~.*!r.*$/ ! s/$/!r g/' input.txt存在,

!g会正确跳过该行,但会将其附加到input.txt中的每一行。

sed '/^height.*$/s/$/!r g/' input.txt,只会正确附加到匹配的行,但如果!r g已经存在,也会正确。

4 个答案:

答案 0 :(得分:2)

我们可以用sed做到这一点。首先,我们选择以height开头且包含~的行。对于这些行,如果该行尚未以该值结尾,我们可以用!r g替换行尾:

#/usr/bin/sed -f

/^height .*~/{
/ !r g$/!s/$/ !r g/
# Explanation:
# / !r g/           : select lines marked with the tag
#       !s          : in lines that don't match, substitute
#          $        : end of line
#             !r g  : the tag to add
}

示范

$ ./45876917.sed <<END
height ~ mu gender
height !bin ~ mu date_birth !r g
height !bin ~ mu gender
END
height ~ mu gender !r g
height !bin ~ mu date_birth !r g
height !bin ~ mu gender !r g

答案 1 :(得分:1)

sed '/^y.*~.*$/{/!r g/!{s/.*/& !r g/}}' input.txt

E.g。

$ cat input.txt
y !n ~ d e f !r g
y ~ a b c

$ sed '/^y.*~.*$/{/!r g/!{s/.*/& !r g/}}' input.txt
y !n ~ d e f !r g
y ~ a b c!r g

<强>更新

以上sed命令会考虑所有带有模式^y.*~.*$的行,并且只有当该行在任何部分中不包含!r g时才会将!r g追加到末尾。线。

要更改已过滤的行,只需将起始正则表达式^y.*~.*$更新为您需要的内容。

答案 2 :(得分:1)

awk 解决方案:

awk '/^y.*~.+/ && !/!r g/{ $0=$0" !r g" }1' input.txt

答案 3 :(得分:1)

awk中的另一个人:

$ awk '{sub(/( !r g)?\r?$/," !r g")}1' file
y ~ a b c !r g
y !n ~ d e f !r g
y !n ~ d e f !r g

或更改数据:

height ~ mu gender !r g
height !bin ~ mu date_birth !r g
height !bin ~ mu gender !r g

注意正则表达式中的\r?,这是结束\r\n的Windows行的第一部分。如果存在,则会被替换。