使用 sed,我想在第 n 次出现后添加检查
输入:
DCR
DCR
DCR
输出:
DCR
DCR
check
DCR
可以使用sed吗?
答案1
使用 GNU sed,您可以替换na 中的第 th 模式线
$ echo "foofoofoofoo" | sed 's/foo/&\nbar/2'
foofoo
barfoofoo
但对于n包含模式的第 3 行,awk 更容易:
awk -v n=2 -v patt=foo '{print} $0 ~ patt && ++count == n {print "bar"}' <<END
foo1
foo2
foo3
foo4
END
foo1
foo2
bar
foo3
foo4
答案2
使用 GNU sed:
sed -z 's/DCR/&\ncheck/2' <input >output
对于非更新版本:
sed '/DCR/{p;s/.*/1/;H;g;/^\(\n1\)\{2\}$/s//check/p;d}' <input >output
DCR
如果一行中出现超过 1 次:
sed '
/DCR/{p
x # tests if already have met pattern
/^\(\n\a\)\{2\}/!{ #+apropriate times and, if so, cancel
x #+the rest of commands
s/DCR/\a/g # exchange DCR by \a symbol
s/^[^\a]*\|[^\a]*$//g # delete everything before & after it
s/[^\a]\+/\n/g # substitute everything between by \n
H
g
/^\(\n\a\)\{2\}/s/.*/check/p} # add 'check' for double pattern
d}' <input >output
答案3
您可以sed
在堆栈上执行此操作...
sed '/match$/N
s/\n/&INSERT&/3;t
$n;N;P;D'
那会插入INSERT
每 3 个之后非顺序的的发生match
在输入中。这是我知道的最有效的方法,sed
因为它不会尝试存储不同之间发生的所有行matches
,也不需要缓冲区交换或反向引用比较,而是简单地增加 的sed
唯一计数方法 - 通过其行周期来增加其行号。
当然,这会增加一些开销 - 每个匹配模式空间都会变得更大一些 - 但它仍然是相同的流,并且没有回溯。只是先进先出- 我认为,这是一种非常适合的方法sed
。事实上,与其回去检查匹配,sed
还不如进一步前进每场比赛。我有点小得意,不知道为什么以前从来没有想到过。
不过,上面的版本会在某种程度上压缩重复,因为它只能在输入后面一行工作。解决方案是进一步推进,并且只需要一点额外的复杂性,即在环路内部设置b
牧场:l
abel 短路环路N;P;D
以保持电流。
它的工作原理如下:
seq 100000| sed -ne':n
s/\n/&\tCheck&\t/5p;t
N;/0000$/bn' -eD
...对我来说,打印...
49995
49996
49997
49998
49999
Check
50000
99995
99996
99997
99998
99999
Check
100000
您会看到,为了维持计数,它会在每次出现时增加其行缓冲区match
并将另一条线钉到图案空间上的滑动窗口上。这样,验证是否已找到匹配所需的就是尝试替换掉s///
nth
\n
模式空间中的 ewline 字符。如果可以的话,我们遇到过n matches
到目前为止,t
est 可以将我们从当前迭代中分支出来并完全清除增量。
在上面的示例中,对于每个以字符串结尾的模式空间,缓冲区都会递增一次0000
。当找到其中 5 个时,sed
打印当前模式空间 - 及其整个缓冲区 - 并清除计数器。
为了你的事:
printf DCR\\n| tee - - - - - |
sed -e:n -e's/\n/&\tCheck&\t/2;t
$n; N;/DCR$/bn' -eP\;D
DCR
DCR
Check
DCR
DCR
DCR
Check
DCR
现在,如果你想标记仅有的这nth
发生,也很简单:
printf DCR\\n |
tee - - - - - - - - -|
sed -e:n -e's/\n/&\tCheck&\t/3;te
$n; N;/DCR$/bn' -e'P;D;:e
n;be'
...如果您仔细观察,您可能会发现我们仅仅触及了表面...
DCR
DCR
DCR
Check
DCR
DCR
DCR
DCR
DCR
DCR
DCR
答案4
GNU sed
sed
不太适合这项任务,但当然你仍然可以做到。这是n
在保留空间中保存很长的字符串的一种方法,并使用它来计算DCR
出现的次数:
n=2
((yes | head -n$n | tr -d \\n; echo); cat infile) |
sed '
1 {h;d} # save counting string
/DCR/ { #
x; s/.//; x # n--
T chk # if n=0 goto "chk"
}
P;D
:chk # insert check
i\check
:a; N; ba # print rest of file
'
awk
正如所指出的格伦,awk 更干净,这是一个高尔夫版本,但类似的逻辑:
<infile awk '!n { print "check" } /DCR/ { n-- } 1' n=2