我有一个具有这种格式的特殊文件:
title1
_1 texthere
title2
_2 texthere
我希望所有以“_”开头的换行符作为第二列放置到之前的行
我尝试使用 sed 和以下命令来做到这一点:
sed 's/_\n/ /g' filename
但它并没有给我我想做的事情(基本上什么都不做)
谁能指出我正确的做法?
谢谢
我有一个具有这种格式的特殊文件:
title1
_1 texthere
title2
_2 texthere
我希望所有以“_”开头的换行符作为第二列放置到之前的行
我尝试使用 sed 和以下命令来做到这一点:
sed 's/_\n/ /g' filename
但它并没有给我我想做的事情(基本上什么都不做)
谁能指出我正确的做法?
谢谢
尝试以下解决方案:
在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
如果您的整个文件就像您的样本(成对的行),那么最简单的答案是
paste - - < file
否则
awk '
NR > 1 && /^_/ {printf "%s", OFS}
NR > 1 && !/^_/ {print ""}
{printf "%s", $0}
END {print ""}
' file
这可能对您有用(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
Perl 方法:
perl -00pe 's/\n_/ /g' file
在这里,-00
perl 以段落模式读取文件的原因,其中“行”由两个连续的换行符定义。在您的示例中,它将整个文件读入内存,因此,\n_
用空格进行简单的全局替换将起作用。
但是,对于非常大的文件,这不是很有效。如果您的数据太大而无法放入内存,请使用以下命令:
perl -ne 'chomp;
s/^_// ? print "$l " : print "$l\n" if $. > 1;
$l=$_;
END{print "$l\n"}' file
在这里,文件被逐行读取(-n
),并从所有行中删除尾随换行符(chomp
)。在每次迭代结束时,当前行保存为$l
( $l=$_
)。在每一行,如果替换成功并且_
从行的开头删除了 a ( s/^_//
),则打印前一行并用空格代替换行符 print "$l "
。如果替换失败,则使用换行符打印上一行。该END{}
块仅打印文件的最后一行。