我有一个文本文件,格式如下。第一行是“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:1736 string , 3
如何将两行合并为一个?
答案 0 :(得分:204)
paste
对这项工作有好处:
paste -d " " - - < filename
答案 1 :(得分:143)
AWK:
awk 'NR%2{printf "%s ",$0;next;}1' yourFile
请注意,输出结尾处有一个空行。
sed的:
sed 'N;s/\n/ /' yourFile
答案 2 :(得分:29)
替代sed,awk,grep:
xargs -n2 -d'\n'
如果您想加入N行,并且只需要以空格分隔的输出,这是最好的。
我的原始答案是xargs -n2
,它在单词而不是行上分隔。 -d
可用于按任何单个字符拆分输入。
答案 3 :(得分:25)
杀狗的方法多于悬挂。 [1]
awk '{key=$0; getline; print key ", " $0;}'
在引号内放置你喜欢的任何分隔符。
参考文献:
答案 4 :(得分:10)
以下是我在bash中的解决方案:
while read line1; do read line2; echo "$line1, $line2"; done < data.txt
答案 5 :(得分:10)
虽然看起来先前的解决方案可行,但如果文档中出现单个异常,则输出将分段。下面有点安全。
sed -n '/KEY/{
N
s/\n/ /p
}' somefile.txt
答案 6 :(得分:10)
以下是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
代表输出记录分隔符。我们在这里做的是使用存储行号的NR
来测试条件。如果NR
的模数是真值(> 0),那么我们将输出字段分隔符设置为FS
(字段分隔符)的值,默认情况下为空格,否则我们分配值RS
(记录分隔符)是换行符。
如果您希望添加,
作为分隔符,请使用以下内容:
awk '{ ORS = (NR%2 ? "," : RS) } 1' file
答案 7 :(得分:7)
&#34;前&#34;是一个可编写脚本的行编辑器,与sed,awk,grep等属于同一个族。我认为它可能就是你要找的东西。许多现代vi克隆/后继者也有vi模式。
ex -c "%g/KEY/j" -c "wq" data.txt
对于每一行,如果匹配&#34; KEY&#34;执行以下行的 j 。在该命令完成后(针对所有行),发出 w 仪式和 q uit。
答案 8 :(得分:4)
如果选择Perl,您可以尝试:
perl -0pe 's/(.*)\n(.*)\n/$1 $2\n/g' file.txt
答案 9 :(得分:4)
您可以使用这样的awk来组合2对线:
awk '{ if (NR%2 != 0) line=$0; else {printf("%s %s\n", line, $0); line="";} } \
END {if (length(line)) print line;}' flle
答案 10 :(得分:3)
使用def find_images_with_keyword(key_dict, keywords_list):
new_list = []
for item in key_dict.items():
key, filenames = item
if key in keywords_list:
for filename in filenames:
if filename not in new_list: # add this
new_list.append(filename)
return new_list
glenn jackman's answer略有不同:如果paste
分隔符选项的值包含多个字符,-d
会逐个循环显示字符,并结合paste
选项在处理相同的输入文件时继续这样做。
这意味着我们可以使用我们想要的任何东西作为分隔符加上转义序列-s
来一次合并两行。
使用逗号:
\n
和美元符号:
$ paste -s -d ',\n' infile
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
无法做的是使用由多个字符组成的分隔符。
作为奖励,如果$ paste -s -d '$\n' infile
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
符合POSIX,则不会修改文件中最后一行的换行符,因此对于具有奇数行的输入文件,例如
paste
KEY 4048:1736 string
3
KEY 0:1772 string
不会对最后一行的分离字符进行处理:
paste
答案 11 :(得分:3)
您还可以使用以下vi命令:
:%g/.*/j
答案 12 :(得分:1)
使用vim的另一种方法是:
:g/KEY/join
这会将join
(应用于其下面的行)应用于其中所有带有单词KEY
的行。结果:
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
答案 13 :(得分:1)
使用vim的另一种解决方案(仅供参考)。
解决方案1 :
在vim vim filename
中打开文件,然后执行命令:% normal Jj
这个命令很容易理解:
之后,保存文件并退出:wq
解决方案2 :
在shell中执行命令vim -c ":% normal Jj" filename
,然后保存文件并以:wq
退出。
答案 14 :(得分:1)
如果我需要组合两行(为了便于处理),但允许数据超过特定的,我发现这是有用的
<强> 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
答案 15 :(得分:1)
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
答案 16 :(得分:0)
更通用的解决方案(允许连接多个后续行)作为shell脚本。这会在每个之间添加一条线,因为我需要可见性,但这很容易解决。这个例子是&#34;键&#34;行结束于:没有其他行。
#!/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
答案 17 :(得分:0)
perl -0pE 's{^KEY.*?\K\s+(\d+)$}{ $1}msg;' data.txt > data_merged-lines.txt
-0
吞噬整个文件而不是逐行阅读;
pE
用循环包装代码并打印输出,请参阅http://perldoc.perl.org/perlrun.html中的详细信息;
^KEY
匹配&#34; KEY&#34;在行的开头,然后是
.*?
)的非贪婪匹配
\s+
,包括换行符; (\d+)
的一个或多个数字$1
; 后跟行$
的结尾。
\K
方便地将左侧的所有内容排除在替换之外,因此{ $1}
仅替换1-2个序列,请参阅http://perldoc.perl.org/perlre.html。
答案 18 :(得分:0)
最简单的方法是:
sed '0~2d' file > 1 && sed '1~2d' file > 2 && paste -d " " 1 2
答案 19 :(得分:-1)
请尝试以下行:
<div class="ui secondary pointing menu">
<a class="active item">
Home
</a>
<a class="item">
Messages
</a>
<a class="item">
Friends
</a>
<div class="right menu">
<a class="ui item">
Logout
</a>
</div>
</div>
<div class="ui segment">
<p></p>
</div>
将分隔符置于
之间while read line1; do read line2; echo "$line1 $line2"; done <old.txt>new_file
e.g。如果分隔符是"$line1 $line2";
,那么:
|
答案 20 :(得分:-2)
您可以像这样使用xargs
:
xargs -a file