我有一个这种格式的特殊文件:
title1
_1 texthere
title2
_2 texthere
我希望所有以“_”开头的换行符作为第二列放在
之前的行我尝试使用sed使用此命令执行此操作:
sed 's/_\n/ /g' filename
但它没有给我我想要做的事情(基本上什么都不做)
有人能指出我这样做的正确方法吗?
由于
答案 0 :(得分:3)
尝试以下解决方案:
在sed中,循环完成后会创建一个标签(:a
),而不匹配最后一行($!
)会追加下一个(N
)并返回标签a
:
:a
$! {
N
b a
}
在此之后,我们将整个文件放入内存中,因此对换行符前面的每个_
进行全局替换:
s/\n_/ _/g
p
一起是:
sed -ne ':a ; $! { N ; ba }; s/\n_/ _/g ; p' infile
产量:
title1 _1 texthere
title2 _2 texthere
答案 1 :(得分:3)
如果你的整个文件就像你的样本(线对),那么最简单的答案就是
paste - - < file
否则
awk '
NR > 1 && /^_/ {printf "%s", OFS}
NR > 1 && !/^_/ {print ""}
{printf "%s", $0}
END {print ""}
' file
答案 2 :(得分:2)
这可能适合你(GNU sed):
sed ':a;N;s/\n_/ /;ta;P;D' file
这可以避免将文件篡改到内存中。
或:
sed -e ':a' -e 'N' -e 's/\n_/ /' -e 'ta' -e 'P' -e 'D' file
答案 3 :(得分:1)
Perl方法:
perl -00pe 's/\n_/ /g' file
这里,-00
导致perl以段落模式读取文件,其中&#34;行&#34;由两个连续的换行符定义。在您的示例中,它将整个文件读入内存,因此,使用空格对\n_
进行简单的全局替换将起作用。
但对于非常大的文件来说,这不是很有效。如果您的数据太大而无法容纳在内存中,请使用:
perl -ne 'chomp;
s/^_// ? print "$l " : print "$l\n" if $. > 1;
$l=$_;
END{print "$l\n"}' file
此处,逐行读取文件(-n
),并从所有行(chomp
)中删除尾随换行符。在每次迭代结束时,当前行保存为$l
($l=$_
)。在每一行中,如果替换成功并且从行的开头_
移除了s/^_//
,那么前一行将打印一个空格代替换行符{{1} }。如果替换失败,则使用换行符打印上一行。 print "$l "
块只打印文件的最后一行。