使用单个sed调用来拆分和grep

时间:2019-06-26 11:24:26

标签: sed

这主要是出于好奇,我正在尝试具有与以下行为相同的行为:

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

5 个答案:

答案 0 :(得分:3)

以下是一些替代方案,基于awksed

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 demoawk解决方案看起来最干净。

详细信息

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