3

我有一个具有这种格式的特殊文件:

title1
_1 texthere
title2
_2 texthere

我希望所有以“_”开头的换行符作为第二列放置到之前的行

我尝试使用 sed 和以下命令来做到这一点:

sed 's/_\n/ /g' filename

但它并没有给我我想做的事情(基本上什么都不做)

谁能指出我正确的做法?

谢谢

4

4 回答 4

3

尝试以下解决方案:

中,循环完成创建标签 ( :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
于 2013-07-22T16:21:47.607 回答
3

如果您的整个文件就像您的样本(成对的行),那么最简单的答案是

paste - - < file

否则

awk '
    NR > 1 &&  /^_/ {printf "%s", OFS} 
    NR > 1 && !/^_/ {print ""} 
    {printf "%s", $0} 
    END {print ""}
' file 
于 2013-07-22T17:12:48.837 回答
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
于 2014-10-04T06:18:42.783 回答
1

Perl 方法:

perl -00pe 's/\n_/ /g' file 

在这里,-00perl 以段落模式读取文件的原因,其中“行”由两个连续的换行符定义。在您的示例中,它将整个文件读入内存,因此,\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{}块仅打印文件的最后一行。

于 2014-10-04T10:10:18.620 回答