在unix中将所有行与列分隔符组合成单行

在unix中将所有行与列分隔符组合成单行

我的 unix 输出为

ABC : 123
DEFG : 4587
MJk : 36

我想将所有行合并为单行,并具有相同的分隔,例如

ABC DEFG MJK : 123 4587 36

我知道使用 awk 在单列中打印输出,即

awk'{print $1}' | tr '\n' ' ' 

但正在打印

ABC DEFG MJK 

不是值 123 4587 36

答案1

$ awk -F: '{a=a $1; b=b $2} END{print a FS b}' file
ABC DEFG MJk : 123 4587 36

最近我们看到很多帖子,人们使用tr '\n' ' '或类似的方法将换行符转换为其他内容。除非在极少数情况下,否则不要这样做,因为它将 POSIX 文本文件(所有 POSIX 文本处理工具都可以读取)转换为其他 YMMV 格式的文件。 POSIX 文本行以 结尾\n,POSIX txt 文件由 POSIX 文本行组成。如果您使用tr或其他任何方式删除所有换行符,那么任何后续 POSIX 文本处理工具(awk、sed 等)可能会将其作为输入执行未定义的行为。

下面是一些您可能意想不到但实际上是由 POSIX 定义的其他行为的示例。假设我们想要将这个多行字符串转换为单个空格分隔的行:

$ printf 'foo\nbar\n' | wc -l
       2

用于tr删除所有\ns:

$ printf 'foo\nbar\n' | tr '\n' ' '
foo bar $
$ printf 'foo\nbar\n' | tr '\n' ' ' | wc -l
       0

与输出 POSIX 文本文件相同的更好方法相比,因此在通过管道传输到时给出更直观的结果wc

$ printf 'foo\nbar\n' | paste -sd ' ' -
foo bar
$ printf 'foo\nbar\n' | paste -sd ' ' - | wc -l
       1

答案2

这可以使用 sed 编辑器通过将下一行附加到 tge 模式空间并在中心冒号周围打乱字段来完成。测试命令循环直到 eof 并在每次迭代中选择下一行。

sed -Ee '
  :a;$!N;s/(.*):(.*)\n(.*):(.*)/\1\3:\2\4/;ta
' file

awk 版本是不言自明的。

awk -F ':' -v ORS='' '
{ a[NR] = $1; b[NR] = $2 }
END {
  a[NR] = a[NR] FS
  for (i=1; i<=2*NR; i++)
     print i<=NR ? a[i] : b[i-NR]
  print RS
}
' file

结果:

ABC DEFG MJK : 123 4587 36

答案3

看来您需要缓冲整个内容。您可以尝试以下操作:

awk '{FNR==1{first=$1; second=$3} FNR>1{first=first " " $1; second=second " " $3} END{printf("%s : %s\n", first, second)}'

这将累积变量中所有行的所有“第一列条目”的内容first,以及变量中“第二列条目”的内容(实际上是第三列,因为从s 的角度来看,它将:形成自己的一列)。awk多变的second。最后,它打印如此累积的缓冲区,并使用:分隔符作为分隔符。

如果前导/尾随空格不是问题,您可以将代码缩短为

awk '{first=first " " $1; second=second " " $3} END{printf("%s : %s\n", first, second)}'

答案4

我宁愿将每一列存储在一个数组中,然后以所需的格式打印它们

awk -F" : " '{a[NR]=$1;b[NR]=$2} END{ for(i=1;i<=NR;i++) printf "%s ",a[i]; printf ": "; for(i=1;i<=NR;i++) printf "%s ",b[i];}' file
  • -F" : "根据" : "分隔符分隔列
  • {a[NR]=$1;b[NR]=$2}创建两个数组indexes = NR(行数)和values =该行中列的值
  • printf按所需顺序打印(printf不会打印 a newline

相关内容