我在VI编辑器中有一个文件,如下所示:
I1 a b c d e f
g h i j k l m
o p q r s t u v
w x y z
I2 a b c d
e f g h i j k l m
n o p q r s t
u v w x y z
I3 a b c d e
f g h i j k l m n
o p q r s t u v w x y z
我正在尝试合并以I(^ I)开头的行之后的3行:
I1 a b c d e f g h i j k l m n o p q r s t u v w x y z
I2 a b c d e f g h i j k l m n o p q r s t u v w x y z
I3 a b c d e f g h i j k l m n o p q r s t u v w x y z
我已经用Google搜索,看看我是否可以在VI编辑器中包含I1
的行(即I
[^I]
之后的行)之后加入3行,并找到了Join将下一行连接到当前行的命令,如:g/^I/norm Jx
。但我想使用此命令将接下来的3行连接到当前行。
如果有人能通过VI Editor或任何脚本语言向我建议一种方法,我们将不胜感激。
答案 0 :(得分:4)
以下是使用awk的一种方法:
awk 'NR>1&&/^I[0-9]/{print ""}{printf "%s", $0}END{print ""}' file.txt
当行号大于1且行开头为" I"后跟一个数字,使用print ""
打印换行符。使用printf
打印每行的内容。在END块中(感谢fedorqui),打印最终换行符。
在您的文件上测试它:
$ awk 'NR>1&&/^I[0-9]/{print ""}{printf "%s", $0}END{print ""}' file.txt
I1 a b c d e fg h i j k l mo p q r s t u vw x y z
I2 a b c de f g h i j k l mn o p q r s tu v w x y z
I3 a b c d ef g h i j k l m no p q r s t u v w x y z
答案 1 :(得分:3)
你几乎就在那里:
:g/^I/norm 4J
:g
采用正则表达式和命令:norm 4J
是" ex"执行"正常模式的命令"命令。即你输入的内容。基于彼得的评论::g/^I/.,+3join
或:g/^I/j4
答案 2 :(得分:2)
如果您确定每个块具有相同的行数,请说4:
:g/^I/norm 4J
如果您无法确定要加入的行数,则问题会变得稍微复杂一些:
:g/^I/norm O " separates every block with a blank line
:g//vipJ " join each block into it's own line
:g/^$/d " removes every blank line
如果你不介意在框外思考一下,这个命令适用于任何块大小:
:%join|s/ I/\rI/g " join the whole buffer into one single line
" then substitute every ' I' with `\rI`
答案 3 :(得分:2)
tr -d "\n" <filename | sed 's/ \+/ /g;s/ I/\nI/g'
输出:
I1 a b c d e f g h i j k l m o p q r s t u v w x y z I2 a b c d e f g h i j k l m n o p q r s t u v w x y z I3 a b c d e f g h i j k l m n o p q r s t u v w x y z
答案 4 :(得分:1)
这个awk
成就了:
awk '/^I[0-9]/ {if (f) print f; f=""} {f=sprintf("%s%s", (f?f FS:""), $0)} END {print f}' file
它不断将行添加到变量f
中。当找到以I
+数字开头的行时,它会打印出来。
给定输入返回:
I1 a b c d e f g h i j k l m o p q r s t u v w x y z
I2 a b c d e f g h i j k l m n o p q r s t u v w x y z
I3 a b c d e f g h i j k l m n o p q r s t u v w x y z
答案 5 :(得分:1)
Perlish答案;
#!/usr/bin/perl
use strict;
use warnings;
while ( <DATA> ) {
chomp;
s/\s+/ /g;
if ( m/^I/ ) { print "\n" };
print;
}
__DATA__
I1 a b c d e f
g h i j k l m
o p q r s t u v
w x y z
I2 a b c d
e f g h i j k l m
n o p q r s t
u v w x y z
I3 a b c d e
f g h i j k l m n
o p q r s t u v w x y z
答案 6 :(得分:1)
纯粹的bash解决方案:
#! /bin/bash
start="I"
cur=
while read line ; do
if test "${line:0:1}" = "$start" ; then
test "$cur" = "" || { echo "$cur" ; cur= ;}
fi
cur+="$line"
done << EOT
I1 a b c d e f
g h i j k l m
o p q r s t u v
w x y z
I2 a b c d
e f g h i j k l m
n o p q r s t
u v w x y z
I3 a b c d e
f g h i j k l m n
o p q r s t u v w x y z
EOT
echo "$cur"
答案 7 :(得分:0)
在Vim上,除了glen和romainl指向的ex命令外,你还可以录制一个宏:
qm/^I<enter>vnJq
然后重复两次:
2@m
解释
m
)^I
V3j
的前一步)