将行转换为列

将行转换为列

我有这样的输入,该行块由空行分隔,需要将行转换为列

输入

HEAD1
IF
FI
GH

HEAD2
PU
GT

HEAD3
FG
DF
YT
GU

需要这样打印:

HEAD1 IF FI GH
HEAD2 PU GT
HEAD3 FG DF YT GU

答案1

$ awk -v RS='' '{ $1 = $1; print }' file
HEAD1 IF FI GH
HEAD2 PU GT
HEAD3 FG DF YT GU

RS输入记录分隔符 为空白而不是默认的换行符时,awk将根据输入中出现的两个或多个连续换行符将输入划分为记录,即一个或多个空白行将被视为标记结束的一个记录。这通常称为awk“段落模式”。

然后代码将第一个字段设置为其自身。这看起来像是一个无操作操作,但它会导致awk重新形成当前的输出记录。使用ORS(输出记录分隔符)和(输出字段分隔符)的默认值OFS(分别是换行符和空格符),因此当打印记录时,所有字段都打印在一行上,中间有空格它们以换行符结尾。

您可以通过修改 的值来获取由其他字符串或字符分隔的字段OFS

$ awk -v RS='' -v OFS='\t' '{ $1 = $1; print }' file
HEAD1   IF      FI      GH
HEAD2   PU      GT
HEAD3   FG      DF      YT      GU
$ awk -v RS='' -v OFS=',' '{ $1 = $1; print }' file
HEAD1,IF,FI,GH
HEAD2,PU,GT
HEAD3,FG,DF,YT,GU
$ awk -v RS='' -v OFS='::' '{ $1 = $1; print }' file
HEAD1::IF::FI::GH
HEAD2::PU::GT
HEAD3::FG::DF::YT::GU

awk代码可以缩短为{ $1 = $1 }; 1,其中尾随1将导致通过无条件调用默认操作来打印当前记录。这是无条件打印当前记录的相当常见的方法。


改为使用sed

$ sed -e '/./ { H; $!d; }' -e 'x; y/\n/ /; s/.//' file
HEAD1 IF FI GH
HEAD2 PU GT
HEAD3 FG DF YT GU

H如果该行包含任何内容,这会将当前行附加到保留空间。该行使用定界换行符附加到保留空间。如果这不是最后一行输入,则模式空间将被丢弃d,并且我们立即从下一行输入开始。

如果当前行为空,我们将保留空间替换为x(由于模式空间为空,因此也具有清除保留空间的效果),用空格替换所有换行符,并删除第一个字符(这将是一个额外的空格字符)。

答案2

awk在段落模式下:

awk -v RS= -v FS='\n' -v OFS=' ' '{
        for (i=1;i<=NF;i++) {
        printf "%s%s", $i, (i<NF ? OFS : ORS)
    }
}' file
HEAD1 IF FI GH
HEAD2 PU GT
HEAD3 FG DF YT GU
  • RS=这样设置RS后,输入记录之间用空行分隔。
  • FS='\n'这样您就可以将每个段落中的每一行视为记录的一个字段。
  • withfor我们遍历所有字段,并printf在条件表达式下打印它们ternary expression:如果 exp1i<NF返回 true,OFS则执行;否则,ORS将被处决。

相关内容