如何打印当前行下一行的第一列?

use*_*046 8 awk text-processing

我有一些这样的文件:

abc 123    
abc 789  
bcd 456  
acb 135
Run Code Online (Sandbox Code Playgroud)

我想打印当前行下一行的第一列。

期望的输出:

abc  123 abc  
abc 789 bcd  
bcd 456 acb  
acb 135 
Run Code Online (Sandbox Code Playgroud)

我更喜欢使用awk。

Ste*_*itt 16

记住上一行:

awk 'NR > 1 { print prev, $1 } { prev = $0 } END { print prev }'
Run Code Online (Sandbox Code Playgroud)

这将按如下方式处理输入:

  • 如果当前行是第二行或更大行,则打印上一行(存储在 中prev,见下一步)和当前行的第一个字段,以输出字段分隔符(默认为空格字符)分隔;
  • 在所有情况下,将当前行存储在prev变量中;
  • 在文件末尾,打印上一行。


Ser*_*nyy 11

替代awk方法:

$ awk 'NR == 1{printf "%s", $0;next}{printf " %s\n%s", $1,$0}' input.txt                                    
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
Run Code Online (Sandbox Code Playgroud)

其工作方式很简单:第一行是特殊情况——我们不使用换行符打印它,并告诉 awk 转到下一行而不执行其他代码块。之后,NR == 1{printf "%s", $0;next}被跳过,但其他部分完成这项工作。

请记住,到目前为止我们打印了一个没有换行符的格式化字符串。因此,printf " %s\n%s",$1,$0现在所做的是打印出第一个单词(并且因为没有换行符,它保留在输出的同一行上),插入换行符,然后整行本身(但不以换行符终止) . 因此,下一个插入的第一个单词将保留在同一行上。过程不断继续,直到我们到达文件末尾。

可能的改进是包含END{print ""}块以插入最终换行符。在某些情况下,结果文件将由其他脚本处理,这可能是可取的。


虽然用户特别要求使用 AWK,但其他语言(例如 Python)可以采用相同的方法打印格式化字符串。为那些对如何在其他语言中实现这一点感到好奇的人提供了 Python 替代方案:

$ awk 'NR == 1{printf "%s", $0;next}{printf " %s\n%s", $1,$0}' input.txt                                    
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
Run Code Online (Sandbox Code Playgroud)

用法如下:

$ ./append_first.py < input.txt                            
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
Run Code Online (Sandbox Code Playgroud)

关于最终换行符的相同想法适用于此。


Zan*_*nna 9

这是一种丑陋的sed方式,只是为了好玩

sed '2,$ s/[^ ]\+/& &/; 2,$ s/ /\n/' file | paste -d ' ' - -
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135 
Run Code Online (Sandbox Code Playgroud)

解释

  • 2,$ 从第二行到最后一行
  • s/[^ ]\+/& &/ 将第一组非空白字符加倍
  • ; 分隔命令,就像在 shell 中一样
  • s/ /\n/ 用换行符替换第一个空格
  • paste -d ' ' - - 把这个烂摊子粘在一起(将第二行附加到第三行,将第四行附加到第三行,等等)