我有一个这样的 CSV 文件:
hostname1 | role1 | environment | tag,list | |
hostname2 | role2 | environment | tag,list,longer | |
hostname3 | role3 | environment | | |
我需要一个sed
表达式,如果之前没有标签,则向带有标签的列(第4列)添加一个新标签,如果已经存在标签,则插入一个带有逗号的新标签。我试过这个:
sed "s/\(^$server |.*|.*|\) \(.*|.*|$\)/\1 new,\2/" testfile.csv
其中服务器在外部定义如下:
server="hostname2"
但它不起作用,并且如果标签列表为空,它就不会处理逗号。
您如何使用 sed 来实现这一点?
答案1
发现正则表达式时常见的错误是认为它们可以用作解析器(因此您会看到诸如“如何使用 REGEX 解析 XML 文件?”之类的问题)。但是,您不能在正则表达式中插入太多逻辑:对于像您这样的复杂问题,您要么需要一个解析器,要么需要一个以上的正则表达式。
如果要使用正则表达式,则需要两个:一个用于非空标签情况,一个用于空标签字段。这两个正则表达式可能如下所示:
s/^(hostname123 \|.*?\|.*?\|\s*)(\S+\s*\|.*?\|)$/\1new,\2/
s/^(hostname123 ?\|.*?\|.*?\|)\s*(\|.*?\|)$/\1 new \2/
这两个表达式可以通过管道一起使用sed
:
sed 'expression1' | sed 'expression2'
或者更好的是,使用以下命令:
sed -r -e '/^'"$server"' \|/ { s/^(.*?\|.*?\|.*?\|\s*)(\S+\s*\|.*?\|)$/\1new,\2/; s/^(.*?\|.*?\|.*?\|)\s*(\|.*?\|)$/\1 new \2/ }' testfile.csv
这比使用两个更有效,sed
因为它不需要解析文件两次。