現在の行の次の行の最初の列を印刷する方法は?


8

私はこのようないくつかのファイルを持っています:

abc 123    
abc 789  
bcd 456  
acb 135

現在行の次の行の最初の列を印刷したい。

望ましい出力:

abc  123 abc  
abc 789 bcd  
bcd 456 acb  
acb 135 

私はawkを使用することを好みます。

回答:


16

前の行を覚えてください:

awk 'NR > 1 { print prev, $1 } { prev = $0 } END { print prev }'

これにより、入力は次のように処理されます。

  • 現在の行が2行目以上の場合は、前の行(に格納されprevます。次の手順を参照)と現在の行の最初のフィールドを出力フィールド区切り文字(デフォルトでは空白文字)で区切って印刷します。
  • すべての場合において、現在の行をprev変数に格納します。
  • ファイルの最後に、前の行を出力します。

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

これが機能する方法は簡単です。最初の行は特殊なケースです-改行なしで印刷し、awkに他のコードブロックを実行せずに次の行に進むように指示します。その後NR == 1{printf "%s", $0;next}はスキップされますが、他の部分が機能します。

今までは改行文字なしでフォーマットされた文字列を印刷したことを思い出してください。したがって、printf " %s\n%s",$1,$0今までに行われていることは、最初の単語が出力される(そして、改行がなかったため、出力の同じ行に留まる)、改行が挿入され、その後、行全体(ただし、改行文字で終了しない)です。 。したがって、次に挿入される最初の単語は同じ行に残ります。ファイルの終わりに到達するまで、プロセスは継続します。

考えられる改善は、END{print ""}最後の改行を挿入するブロックを含めることです。結果のファイルが他のスクリプトによって処理される特定のケースでは、それが望ましい場合があります。


ユーザーが特にAWKを要求した場合、フォーマットされた文字列の印刷と同じアプローチを他の言語、たとえばPythonで行うことができます。他の言語でこれをどのように実装できるかについて興味がある人のために提供されているPythonの代替:

#!/usr/bin/env python
from __future__ import print_function
import sys

old = None
for index,line in enumerate(sys.stdin):
    if index == 0:
        print(line.strip(),end=" ")
        continue
    words = line.strip().split()
    print(words[0] + "\n" + line.strip(),end=" ")

そして、そのような使い方:

$ ./append_first.py < input.txt                            
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135

最終改行についても同じことが当てはまります。


9

sed楽しみのための醜い方法があります

sed '2,$ s/[^ ]\+/& &/; 2,$ s/ /\n/' file | paste -d ' ' - -
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135 

説明

  • 2,$ 2行目から最後まで
  • s/[^ ]\+/& &/ 非空白文字の最初のセットを2倍にする
  • ; シェルのようにコマンドを分離します
  • s/ /\n/ 最初のスペースを改行で置き換える
  • paste -d ' ' - - この混乱をくっつける(2行目を3行目に追加、4行目を3行目に追加する、など)

1
別の方法としては、使用することができsedずに独自にpastesed -r 'N;s/\n(\w+)/\1&/;P;D' somefile.txt
デジタルトラウマ

1
sedおもしろいプログラムを書いているなら、おそらくcode-golfを試してみてください;-)
Digital Trauma '13

1
@DigitalTrauma彼女はすでに2か月間コードゴルフに参加しています;)
Sergiy Kolodyazhnyy 2017年

1

私の意見では、最も単純で最も読みやすいアプローチは次のとおりです。

  1. 最初の列を抽出する(cut
  2. 抽出した列から最初の行を削除します(tail
  3. この列をソースファイルに貼り付けます(paste

例:サンプルのinpultファイル:

abc 123    
abc 789  
bcd 456  
acb 135

次に、ターミナルで次のコマンドを実行します

cut -d' ' -f1 in.txt | tail -n +2 | paste -d' ' file -

出力:

abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135

このソリューションの背後にある構造は、与えられた回答とは異なります。条件、ループ、正規表現は必要ありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.