有没有办法仅使用cat和sed打印“ 4”的第4个匹配项到“ 8”的第8个匹配项?
我可以使用=,N,p,q,s作为提示,但不确定如何使用这些
例如,
$ cat foo
1
2
3
4
5-
alkjvearv four
four
asdfasd four
----fourth asdf
qlvkjqrvlj eight
5+
6
7
8
9
eight eight eight
10
11
12 eight
13 eight
eight qorivjqoerijv
----this is eighth
eight
15
$ cat foo | sed ~
----fourth asdf
qlvkjqrvlj eight
5+
6
7
8
9
eight eight eight
10
11
12 eight
13 eight
eight qorivjqoerijv
----this is eighth
据我所知
$ cat foo | sed -n '/four/,/eight/p'
alkjvearv four
four
asdfasd four
----fourth asdf
qlvkjqrvlj eight
答案 0 :(得分:2)
由于您的问题不太精确,因此不确定它是否与您的需求完全匹配,但这可能会给您一个想法。当然,您不应该使用此解决方案(使用awk
)。
字符串uuid1
和uuid2
可以用文件中不存在的任何两个字符串替换。
sed -E -e 'H;1h;$!d;x' \
-e 's/four/uuid1/' -e 's/four/uuid1/' -e 's/four/uuid1/' \
-e 's/eight/uuid2/' -e 's/eight/uuid2/' -e 's/eight/uuid2/' -e 's/eight/uuid2/' \
-e 's/eight/uuid2/' -e 's/eight/uuid2/' -e 's/eight/uuid2/' foo |
sed -n '/four/,/eight/p;/eight/q' |
sed 's/uuid1/four/g;s/uuid2/eight/g'
返回:
----fourth asdf
qlvkjqrvlj eight
5+
6
7
8
9
eight eight eight
10
11
12 eight
13 eight
eight qorivjqoerijv
----this is eighth
我认为是正确的。
命令说明:
sed -E -e 'H;1h;$!d;x'
来自this
sed命令H; 1h; $!d; x读取了整个文件。
由于上面没有使用任何GNU扩展,因此它应该适用于 BSD(OSX)sed。注意,请注意,这种方法需要 能处理长线。 GNU sed应该没问题。那些使用非GNU的人 sed版本应测试其处理长行的能力。
-e 's/four/uuid1/' -e 's/four/uuid1/' -e 's/four/uuid1/' \
-e 's/eight/uuid2/' -e 's/eight/uuid2/' -e 's/eight/uuid2/' -e 's/eight/uuid2/' \
-e 's/eight/uuid2/' -e 's/eight/uuid2/' -e 's/eight/uuid2/' foo
然后我将前三个four
替换为uuid1
,并将前七个eight
替换为uuid2
。
正如@JonathanLeffler所说,如果增加替换数量会变得非常难看,但是我没有找到POSIX sed版本的任何解决方法,我使用了此answer中的命令。
如果GNU sed不可用,而您想更改前3个 从旧到新的出现,然后使用三个s命令:
当k为小数时,此方法效果很好,但缩放至大k时效果很差。
sed -n '/four/,/eight/p;/eight/q'
-默认情况下不打印;从第一个four
到第一个eight
,打印该行;当您找到eight
时,请退出。
我首先尝试了此操作:sed -n '/four/,/eight/p'
,但它可能会在应该打印的部分之后返回行。我使用this answer来解决此问题。
此命令选择第一个four
和第一个eight
出现之间的行。
sed 's/uuid1/four/g;s/uuid2/eight/g'
我将uuid替换为其原始值。即使对于uuid1
,我也会这样做,因为第三个four
与第四个可能在同一行。
答案 1 :(得分:0)
这可能对您有用(GNU sed):
sed ':a;h;s/four/&/4;tb;$d;N;ba;:b;s/eight/&/8;tc;$d;N;bb;:c;x;s/.*\n//;G;s/$/\n/;s/^\([^\n]*\n\).*\1/\1/;s/\n$//;q' file
此命令使用替换命令来检查在处理输入文件时是否已考虑开始/结束字符串。命令s/someString/&/n
本身代替了someString
的第n次出现。如果替换成功,替换命令还将内部标志设置为true。 t
命令允许sed测试内部标志并跳转到sed命令脚本中的另一点,例如如果最后一次替换成功,ta
将跳到sed脚本中发生:a
的位置。一旦进行了跳转或调用了新的sed周期,内部标志就会重置为false。此机制用于计算开始/结束条件的任意字符串。满足两个条件并删除起始边界之前的部分后,就可以终止输入文件的处理,并打印或不打印结果。
起始条件之前的文本部分的删除可能导致许多边缘情况。为了简化它们,在最终结果中添加了换行符,然后将其删除。
一种更容易但容易出现的错误解决方案:
sed -z 's/four/\x00&/4;s/eight/\x00&/8' file |
sed '/\x00four/,/\x00eight/!d;s/\x00\(four\)/\1/;s/\x00\(eight\)/\1/'