这主要是出于好奇,我正在尝试具有与以下行为相同的行为:
echo -e "test1:test2:test3"| sed 's/:/\n/g' | grep 1
在单个sed
命令中。
我已经尝试过
echo -e "test1:test2:test3"| sed -e "s/:/\n/g" -n "/1/p"
但是出现以下错误:
sed: can't read /1/p: No such file or directory
关于如何解决此问题并将不同类型的命令组合到单个sed
调用中的想法?
当然,与实际用例相比,这过于简化了,我知道我可以通过使用多个调用来解决问题,这再次出于好奇。
编辑:我对sed
工具最感兴趣,我已经知道如何使用其他工具甚至是这些工具的组合。
EDIT2:这是一个更现实的脚本,更接近我想要实现的目标:
arch=linux64
base=https://chromedriver.storage.googleapis.com
split="<Contents>"
curl $base \
| sed -e 's/<Contents>/<Contents>\n/g' \
| grep $arch \
| sed -e 's/^<Key>\(.*\)\/chromedriver.*/\1/' \
| sort -V > out
我想简化的是卷曲线,将其变成类似:
curl $base \
| sed 's/<Contents>/<Contents>\n/g' -n '/1/p' -e 's/^<Key>\(.*\)\/chromedriver.*/\1/' \
| sort -V > out
答案 0 :(得分:3)
以下是一些替代方案,基于awk
和sed
:
sed -E "s/(.*:)?([^:]*1[^:]*).*/\2/" <<< "test1:test2:test3"
awk -v RS=":" '/1/' <<< "test1:test2:test3"
# or also
awk 'BEGIN{RS=":"} /1/' <<< "test1:test2:test3"
或者,使用您的逻辑,您需要通过管道传递第二条sed
命令:
sed "s/:/\n/g" <<< "test1:test2:test3" | sed -n "/1/p"
请参见this online demo。 awk
解决方案看起来最干净。
详细信息
在sed
解决方案中,(.*:)?([^:]*1[^:]*).*
模式匹配任意0+个字符和一个:
的可选序列,然后将除{{1}之外的0个或多个字符捕获到组2中},:
,还是1
以外的0个或多个字符,然后与该行的其余部分匹配。替换只是保留第2组的内容。
在:
解决方案中,记录分隔符设置为awk
,然后使用:
正则表达式仅返回其中包含/1/
的记录。
答案 1 :(得分:2)
这可能对您有用(GNU sed):
sed 's/:/\n/;/^[^\n]*1/P;D' file
替换每个:
,如果图案空间的第一行包含1
,请打印它。
重复。
替代方法:
sed -Ez 's/:/\n/g;s/^[^1]*$//mg;s/\n+/\n/;s/^\n//' file
这会将整个文件插入到内存中,并用换行符替换所有冒号。删除所有不包含1的行,并删除多余的换行符。
答案 2 :(得分:1)
echo -e "test1:test2:test3" | sed -En 's/:/\n/g;/^[^\n]*2[^\n]*(\n|$)/P;//!D'
sed -n
,否则不会打印sed -E
允许使用括号匹配(\n|$)
,这是换行符或模式空间的结尾P
将图案缓冲区打印到第一行。D
将模式缓冲区修剪到第一行换行符[^\n]
是与换行符之外的所有字符匹配的字符类//
是重复比赛的简写//!
然后匹配以前不匹配的所有内容因此,在分成换行符之后,您要确保2
字符位于模式缓冲区^
的开头和第一个换行符之间。
而且,如果没有您要查找的字符,则要D
删除直到第一行。
此时,它适用于一行输入,其中一个字符串包含您要查找的字符。
要在一行中扩展到多个匹配项,您必须ta
,有条件地分支回到标签:a
:
$ printf "test1:test2:test3\nbob3:bob2:fred2\n" | \
sed -En ':a s/:/\n/g;/^[^\n]*2[^\n]*(\n|$)/P;D;ta'
test2
bob2
fred2
答案 3 :(得分:1)
真正丑陋的sed的替代方法是:grep -o '\w*2\w*'
$ printf "test1:test2:test3\nbob3:bob2:fred2\n" | grep -o '\w*2\w*'
test2
bob2
fred2
grep -o
:仅匹配或者:grep -o '[^:]*2[^:]*'
答案 4 :(得分:0)
这根本不是sed的工作。对于多字符RS,使用GNU awk:
$ echo "test1:test2:test3:test4:test5:test6"| awk -v RS='[:\n]' '/1/'
test1
$ echo "test1:test2:test3:test4:test5:test6"| awk -v RS='[:\n]' 'NR%2'
test1
test3
test5
$ echo "test1:test2:test3:test4:test5:test6"| awk -v RS='[:\n]' '!(NR%2)'
test2
test4
test6
$ echo "foo1:bar1:foo2:bar2:foo3:bar3" | awk -v RS='[:\n]' '/foo/ || /2/'
foo1
foo2
bar2
foo3
使用任何awk,您只需要在最终记录上去除\n
,然后对其进行操作即可:
$ echo "test1:test2:test3:test4:test5:test6"| awk -v RS=':' '{sub(/\n$/,"")} /1/'
test1