我有这个输入文件:
...
https://long-url/something?value1=999&something=xyz?value2=555
https://long-url/something?value1=534&something=xyz?value2=2312
https://long-url/something?value1=534&something=xyz?value2=233
https://long-url/something?value1=534
...
我想捕获 value1 和 value2 并将它们输出为 csv,并删除任何不匹配的行:
...
999,555
534,2312
534,233
...
我在捕获值方面没有问题,但在删除任何不需要的行时遇到问题:
sed 's/.*categoryid=\([0-9]*\).*courseid=\([0-9]*\).*/\1,\2/g;/^[^0-9]\+/d' input-file
基本上,它/^[^0-9]\+/d
没有按预期工作。我以为它会删除任何不以任何数字开头的行,但相反,它给了我:
999,555
534,2312
534,233
我的 sed 版本:sed (GNU sed) 4.7
答案1
您正在使用一个代替,后面跟着一个删除:
sed -e 's/.../.../g' -e '/.../d'
这有点不稳定,因为您/.../d
可能会意外地匹配文件内容中的其他内容。
相反,我只会打印受替代影响的行。这可以通过(以避免默认打印)来完成-n
,然后添加p
到行尾以打印匹配的行。这避免了第二次声明的需要sed
。
sed -ne 's/.../.../gp'
我还会删除尾随,g
因为每行不需要多个匹配项:
sed -ne 's/.../.../p'
结果是:
sed -ne 's/.*categoryid=\([0-9]*\).*courseid=\([0-9]*\).*/\1,\2/p' input-file
行动中:
$ sed -ne 's/.*value1=\([0-9]*\).*value2=\([0-9]*\).*/\1,\2/p' << EOF
https://long-url/something?value1=999&something=xyz?value2=555
https://long-url/something?value1=534&something=xyz?value2=2312
https://long-url/something?value1=534&something=xyz?value2=233
https://long-url/something?value1=534
EOF
输出
999,555
534,2312
534,233
答案2
您的表达式^[^0-9]\+
强制匹配至少一个非数字,这意味着空行不会匹配它,因为它们不包含非数字。
就我个人而言,我会按以下方式执行此操作:
sed -e '/.*categoryid=\([0-9]*\).*courseid=\([0-9]*\).*/!d' \
-e 's//\1,\2/' input-file
这首先会删除与特定正则表达式不匹配的所有行(例如空行)。第二个表达式执行替换。当使用空模式时(如第二个表达式中的替换),将重新使用最近使用的模式。
请注意,您不需要/g
在替换命令的末尾,因为您只希望每个输入行匹配一次模式。
答案3
要匹配/^[^0-9]\+/
,该行必须至少包含一个字符,即不能为空。
只是不要删除以数字开头的行:
/^[0-9]/!d