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

时间:2016-09-13 16:03:18

标签: linux awk sed vi

我想添加一个符号" >>"在第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)

6 个答案:

答案 0 :(得分:1)

您可以使用awk

执行此操作
awk '{if ((NR-1) % 5) {print $0} else {print $0 " >>"}}'

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

注意:上面的代码每5行输出一次后缀,因为这是您的示例工作所需的内容。

答案 1 :(得分:0)

你可以采取多种方式。 sed在选择行时有点奇怪,但它可行。 E.g:

<强> SED

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

您也可以将此作为 perl one-liner:

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

答案 2 :(得分:0)

你在考虑这个错误。您应该追加到每个段落的第一行的末尾,不要担心在任何给定段落中发生了多少行。那只是:

$ 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)

答案 3 :(得分:0)

这可能适合你(GNU sed):

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

答案 4 :(得分:0)

这是Awk中的非数字方式。如果我们有一个支持RS变量长度超过一个字符的Awk,则此方法有效。我们根据空行分隔将数据分成记录:"\n\n"。在这些记录中,我们在换行符上打破字段。因此,$1是单词,$2是定义,$3是引用,$4是来源:

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

我们使用相同的输出分隔符作为输入分隔符。然后,我们唯一的模式/操作步骤是编辑$1,以便它上面有>>。默认操作是{ print },这就是我们想要的:打印每条记录。所以我们可以省略它。

更短:从RS的连接中初始化FS

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

这很有表现力:它表示该格式使用两个连续的字段分隔符来分隔记录。

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

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

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

awk '(NR-1)%5?1:$0=$0" >>"'

我们可以使用三元条件表达式cond ? then : else作为模式,将操作留空,以便默认为{print},这当然意味着{print $0}。如果从零开始的记录号是全等到0,模5,那么我们生成1来触发打印操作。否则我们评估`$ 0 = $ 0&#34; &GT;&GT;&#34;添加所需的后缀到记录。此表达式的结果也是布尔值true,用于触发打印操作。

剃掉一个角色:我们不必从NR中减去1,然后测试同余到零。基本上,每当基于1的记录号与1一致,模5时,我们就要添加>>后缀:

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

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

我们可以做得更好(有一些假设):我们可以做的是通过分配参数来创建包含$0的第二个字段,而不是编辑>> $2。隐式print操作将打印此内容,由空格偏移:

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

但这仅在定义行包含一个单词时才有效。如果此词典中的任何单词是复合名词(由空格分隔,而不是连字符),则会失败。如果我们试图修复这个缺陷,我们很遗憾地回到了同样的长度:

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

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

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

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

测试NR == 1(mod 5)的不同方式:即regexp!

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

再次,不是最简洁,但似乎值得一提。我们可以将NR视为表示整数为十进制数字的字符串。如果它以16结束,则它与1,mod 5一致。显然,不容易修改为其他模数,更不用说计算上令人作呕了。

答案 5 :(得分:0)

还有几个:

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

$ awk '$0=$0(NR%5==1?">>>":"")' foo