如何从命令行将每两行合并成一行?
我有一个以下格式的文本文件。 第一行是“KEY”,第二行是“VALUE”。
KEY 4048:1736 string 3 KEY 0:1772 string 1 KEY 4192:1349 string 1 KEY 7329:2407 string 2 KEY 0:1774 string 1
我需要和键一样的值。 所以输出应该是这样的…
KEY 4048:1736 string 3 KEY 0:1772 string 1 KEY 4192:1349 string 1 KEY 7329:2407 string 2 KEY 0:1774 string 1
如果我可以使用一些分隔符如$或KEY 4048:1736string3,会更好
如何将两行合并成一行?
AWK:
awk 'NR%2{printf "%s ",$0;next;}1' yourFile
请注意,输出结尾处有一个空行。
SED:
sed 'N;s/\n/ /' yourFile
paste
这个工作是好的:
paste -d " " - - < filename
杀死一条狗的方法比悬挂更多。 [1]
awk '{key=$0; getline; print key ", " $0;}'
把你喜欢的任何分隔符放在引号内。
参考文献:
- 最初的“皮肤猫的方法很多”,恢复到一个较旧的,也可能是起源的expression,也没有任何关系与宠物。
替代sed,awk,grep:
xargs -n2 -d'\n'
这是最好的,当你想要joinN行,你只需要空格分隔输出。
我原来的答案是xargs -n2
,它在单词而不是线条上分开。 -d
可以用来分割任何单个字符的input。
这里是我在bash中的解决scheme:
while read line1; do read line2; echo "$line1, $line2"; done < data.txt
虽然看起来以前的解决scheme是可行的,但如果在文档中出现单个exception,输出将会变成碎片。 下面有点安全。
sed -n '/KEY/{ N s/\n/ /p }' somefile.txt
这是awk
另一种方法:
awk 'ORS=NR%2?FS:RS' file
$ cat file KEY 4048:1736 string 3 KEY 0:1772 string 1 KEY 4192:1349 string 1 KEY 7329:2407 string 2 KEY 0:1774 string 1
$ awk 'ORS=NR%2?FS:RS' file KEY 4048:1736 string 3 KEY 0:1772 string 1 KEY 4192:1349 string 1 KEY 7329:2407 string 2 KEY 0:1774 string 1
正如Ed Morton在评论中指出的那样,最好在安全性和可携带性方面增加支架。
awk '{ ORS = (NR%2 ? FS : RS) } 1' file
ORS
代表输出logging分隔符。 我们在这里做的是使用存储行号的NR
来testing一个条件。 如果NR
的模是一个真值(> 0),那么我们将输出字段分隔符设置为FS
(字段分隔符)的值,默认为空格,否则我们分配换行符的RS
(logging分隔符)的值。
如果你想添加,
作为分隔符,然后使用以下内容:
awk '{ ORS = (NR%2 ? "," : RS) } 1' file
“ex”是一个脚本行编辑器,与sed,awk,grep等在同一个家族中。我想这可能是你正在寻找的东西。 许多现代的vi克隆/后继者也有vi模式。
ex -c "%g/KEY/j" -c "wq" data.txt
这表示对于每一行,如果它匹配“KEY”,则执行以下行中的某个行。 在这个命令完成之后(针对所有行),发出一个wRite并且把它给你。
如果Perl是一个选项,你可以尝试:
perl -0pe 's/(.*)\n(.*)\n/$1 $2\n/g' file.txt
你可以像这样使用awk来结合2对线:
awk '{ if (NR%2 != 0) line=$0; else {printf("%s %s\n", line, $0); line="";} } \ END {if (length(line)) print line;}' flle
你也可以使用下面的vi命令:
:%g/.*/j
nawk '$0 ~ /string$/ {printf "%s ",$0; getline; printf "%s\n", $0}' filename
这读作为
$0 ~ /string$/ ## matches any lines that end with the word string printf ## so print the first line without newline getline ## get the next line printf "%s\n" ## print the whole line and carriage return
在我需要结合两条线(为了更容易处理)的情况下,但是允许数据超过特定的情况,我发现这是有用的
data.txt中
string1=x string2=y string3 string4
cat data.txt | nawk'$ 0〜/ string1 = / {printf“%s”,$ 0; 函数getline; printf“%s \ n”,$ 0; getline} {print}'> converted_data.txt
输出结果如下所示:
converted_data.txt
string1=x string2=y string3 string4
另一个使用vim的解决scheme(仅供参考)。
解决scheme1 :
在vim vim filename
打开文件,然后执行命令:% normal Jj
这个命令退出容易理解:
- %:对于所有的行,
- 正常:执行正常命令
- Jj:执行join命令,然后跳转到下一行
之后,保存文件并退出:wq
解决scheme2 :
在shell中执行命令vim -c ":% normal Jj" filename
,然后保存该文件并退出:wq
。
最简单的方法是:
- 删除偶数行并将其写入临时文件1中。
- 删除奇数行并将其写入临时文件2中。
- 将两个文件合并为一个通过使用粘贴命令与-d(意味着删除空间)
sed '0~2d' file > 1 && sed '1~2d' file > 2 && paste -d " " 1 2
perl -0pE 's{^KEY.*?\K\s+(\d+)$}{ $1}msg;' data.txt > data_merged-lines.txt
-0
吞下整个文件,而不是逐行阅读;
pE
用循环打包代码并打印输出,详见http://perldoc.perl.org/perlrun.html ;
^KEY
在行开头匹配“KEY”,之后是任何事物( .*?
)的非贪婪匹配
- 任何种类的一个或多个空格,包括换行符;
- 一个或多个数字
(\d+)
,我们捕获并稍后重新插入为$1
;
之后是$
行的结尾。
\K
方便地将其左侧的所有内容从replace中排除,因此{ $1}
仅replace1-2个序列,请参阅http://perldoc.perl.org/perlre.html 。
一个更通用的解决scheme(允许连接多个后续行)作为shell脚本。 这在每个之间添加了一条线,因为我需要可见性,但是这很容易修复。 这个例子是“关键”行结束的地方:没有其他的行。
#!/bin/bash # # join "The rest of the story" when the first line of each story # matches $PATTERN # Nice for looking for specific changes in bart output # PATTERN='*:'; LINEOUT="" while read line; do case $line in $PATTERN) echo "" echo $LINEOUT LINEOUT="$line" ;; "") LINEOUT="" echo "" ;; *) LINEOUT="$LINEOUT $line" ;; esac done
尝试以下行:
while read line1; do read line2; echo "$line1 $line2"; done <old.txt>new_file
把分隔符放在中间
"$line1 $line2";
例如,如果分隔符是|
, 然后:
"$line1|$line2";
你可以像这样使用xargs
:
xargs -a file