如何在行尾附加任何字符串并在特定行数之后继续执行?

How can I append any string at the end of line and keep doing it after specific number of lines?

我想在第 1 行和第 5 行的末尾添加一个符号“>>”,依此类推。 1,5,9,13,17,....我在网上搜索并浏览了下面的文章,但我无法实现。请帮忙。

How can I append text below the specific number of lines in sed?

retentive
good at remembering
The child was very sharp, and her memory was extremely retentive. 
— Rowlands, Effie Adelaide

unconscionable
greatly exceeding bounds of reason or moderation
For generations in the New York City public schools, this has become the norm with devastating consequences rooted in unconscionable levels of student failure. 
— New York Times (Nov 4, 2011)

输出应该像-

retentive >>
good at remembering
The child was very sharp, and her memory was extremely retentive. 
— Rowlands, Effie Adelaide

unconscionable >>
greatly exceeding bounds of reason or moderation
For generations in the New York City public schools, this has become the norm with devastating consequences rooted in unconscionable levels of student failure. 
— New York Times (Nov 4, 2011)

你可以用 awk:

awk '{if ((NR-1) % 5) {print [=10=]} else {print [=10=] " >>"}}'

我们检查行号减 1 是否是 5 的倍数,如果是,我们输出该行后跟一个 >>,否则,我们只输出该行。

注意:以上代码每 5 行输出后缀,因为这是您的示例工作所需要的。

您可以通过多种方式进行。 sed 在选择行时有点奇怪,但它是可行的。例如:

sed:

sed -i -e 's/$/ >>/;n;n;n;n' file

你也可以用 perl 一行:

perl -pi.bak -e 's/(.*)/ >>/ if not (( $. - 1 ) % 5)' file

你想错了。您应该附加到每个段落的第一行末尾,不要担心任何给定段落中恰好有多少行。那只是:

$ awk -v RS= -v ORS='\n\n' '{sub(/\n/," >>&")}1' file
retentive >>
good at remembering
The child was very sharp, and her memory was extremely retentive.
— Rowlands, Effie Adelaide

unconscionable >>
greatly exceeding bounds of reason or moderation
For generations in the New York City public schools, this has become the norm with devastating consequences rooted in unconscionable levels of student failure.
— New York Times (Nov 4, 2011)

这可能适合您 (GNU sed):

sed -i '1~4s/$/ >>/' file

这是 Awk 中的一种非数字方式。 如果我们有一个支持 RS 变量长度超过一个字符的 Awk,它就可以工作。我们根据空行分隔将数据分成记录:"\n\n"。在这些记录中,我们在换行处换行。因此 </code> 是单词,<code> 是定义,</code> 是引用,<code> 是来源:

awk 'BEGIN {OFS=FS="\n";ORS=RS="\n\n"} =" >>"'

我们使用与输入分隔符相同的输出分隔符。然后,我们唯一的 pattern/action 步骤是编辑 </code>,使其具有 <code>>>。默认操作是 { print },这就是我们想要的:打印每条记录。所以我们可以省略它。

更短:FS.

的串联初始化 RS
awk 'BEGIN {OFS=FS="\n";ORS=RS=FS FS} =" >>"'

这表达得很好:它说该格式使用两个连续的字段分隔符来分隔记录。

如果我们使用一个标志,初始重置,在每个空白行重置,会怎样?这个解决方案仍然不依赖于硬编码数字,只是空白行分离。该规则在第一行触发,因为 C 的计算结果为零,然后在每个空行之后触发,因为我们将 C 重置为零:

awk 'C++?1:[=12=]=[=12=]" >>";!NF{C=0}'

已接受的 Awk 解决方案的较短版本:

awk '(NR-1)%5?1:[=13=]=[=13=]" >>"'

我们可以使用三元条件表达式 cond ? then : else 作为模式,将操作留空,以便它默认为 {print},这当然意味着 {print [=34=]}。如果从零开始的记录数是 not 等于 0,modulo 5,那么我们产生 1 来触发打印动作。否则,我们评估 `$0=$0" >>" 以将所需的后缀添加到记录中。该表达式的结果也是一个布尔值 true,它触发打印操作。

再减去一个字符: 我们不必从 NR 中减去 1,然后测试是否为零。基本上只要从 1 开始的记录数等于 1,modulo 5,那么我们要添加 >> 后缀:

awk 'NR%5==1?[=14=]=[=14=]" >>":1'

虽然我们必须添加 ==1(+3 个字符),但我们赢了,因为我们可以去掉两个括号和 -1(-4 个字符)。

我们可以做得更好(有一些假设): 我们可以做的不是编辑 [=40=],而是创建第二个字段,其中包含 >>通过分配给参数 </code>。隐式 <code>print 操作将打印此内容,由 space:

偏移
awk 'NR%5==1?=">>":1'

但这只适用于定义行包含一个词的情况。如果这本词典中的任何单词是复合名词(由 space 分隔,没有连字符),则失败。如果我们试图修复这个缺陷,我们会很遗憾地回到原来的长度:

awk 'NR%5==1?$++NF=">>":1'

方法略有不同: 我们为什么不有条件地安装 >>\n 而不是试图将 >> 添加到记录或最后一个字段as ORS, 输出记录分隔符?

awk 'ORS=(NR%5==1?" >>\n":"\n")'

不是最简洁的,但值得一提。它显示了我们如何在记录之间动态地使用其中一些变量。

不同的测试方式 NR == 1 (mod 5): 即正则表达式!

awk 'NR~/[16]$/?[=18=]=[=18=]" >>":1'

同样,不是最简洁,但似乎值得一提。我们可以将 NR 视为将整数表示为十进制数字的字符串。如果以16结尾则全等1,mod5。显然,不容易mod化为其他moduli,不更不用说计算上的恶心了。

还有几个:

$ awk 'NR%5==1 && sub(/$/,">>>") || 1 ' foo

$ awk '[=11=]=[=11=](NR%5==1?">>>":"")' foo