Bagaimana cara mencetak kolom pertama dari baris berikutnya pada baris saat ini?

8

Saya punya beberapa file seperti ini:

abc 123    
abc 789  
bcd 456  
acb 135

Saya ingin mencetak kolom pertama dari baris berikutnya di baris saat ini.

Output yang diinginkan:

abc  123 abc  
abc 789 bcd  
bcd 456 acb  
acb 135 

Saya lebih suka menggunakan awk.

pengguna2905046
sumber

Jawaban:

16

Hafalkan baris sebelumnya:

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

Ini memproses input sebagai berikut:

  • jika garis saat ini adalah yang kedua atau lebih besar, cetak garis sebelumnya (disimpan dalam prev, lihat langkah berikutnya) dan bidang pertama dari garis saat ini, dipisahkan oleh pemisah bidang keluaran (karakter spasi secara default);
  • dalam semua kasus, simpan baris saat ini dalam prevvariabel;
  • di akhir file, cetak baris sebelumnya.
Stephen Kitt
sumber
11

awkPendekatan alternatif :

$ 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

Cara kerjanya sederhana: baris pertama adalah huruf khusus - kami mencetaknya tanpa baris baru, dan meminta awk untuk membuka baris berikutnya tanpa mengeksekusi blok kode lain. Setelah itu, NR == 1{printf "%s", $0;next}dilewati, tetapi bagian lain melakukan pekerjaan.

Ingat bahwa hingga sekarang kami mencetak string yang diformat tanpa karakter baris baru. Jadi, apa yang sedang dilakukan printf " %s\n%s",$1,$0sekarang adalah kata pertama dicetak (dan karena tidak ada baris baru, itu tetap pada baris output yang sama), baris baru dimasukkan, dan kemudian seluruh baris itu sendiri (tetapi tidak berakhir dengan karakter baris baru) . Dengan demikian kata pertama yang dimasukkan berikutnya akan tetap berada pada baris yang sama. Proses berlanjut dan terus sampai kita mencapai akhir file.

Kemungkinan peningkatan adalah memasukkan END{print ""}blok untuk memasukkan baris terakhir. Dalam kasus tertentu di mana file yang dihasilkan akan diproses oleh skrip lain mungkin diinginkan.


Sementara pengguna meminta AWK secara khusus, pendekatan yang sama dengan mencetak string yang diformat dapat diambil dengan bahasa lain, misalnya Python. Alternatif Python disediakan bagi mereka yang penasaran tentang bagaimana ini dapat diimplementasikan dalam bahasa lain:

#!/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=" ")

Dan penggunaannya seperti ini:

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

Gagasan yang sama tentang baris terakhir final juga berlaku di sini.

Sergiy Kolodyazhnyy
sumber
9

Ini sedcara jelek hanya untuk bersenang-senang

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

Penjelasan

  • 2,$ dari baris kedua ke baris terakhir
  • s/[^ ]\+/& &/ gandakan set pertama karakter bukan spasi putih
  • ; memisahkan perintah, seperti di shell
  • s/ /\n/ ganti spasi pertama dengan baris baru
  • paste -d ' ' - - rekatkan kekacauan ini (tambahkan baris kedua ke ketiga, baris keempat ke ketiga, dll)
Zanna
sumber
1
Atau Anda dapat menggunakan sedsendiri tanpa paste:sed -r 'N;s/\n(\w+)/\1&/;P;D' somefile.txt
Digital Trauma
1
Jika Anda menulis sedprogram untuk bersenang-senang, maka mungkin Anda harus mencoba kode-golf ;-)
Digital Trauma
1
@DigitalTrauma dia sudah bermain kode-golf selama 2 bulan;)
Sergiy Kolodyazhnyy
1

Menurut pendapat saya pendekatan yang paling sederhana dan paling mudah dibaca adalah:

  1. ekstrak kolom pertama ( cut)
  2. hapus baris pertama dari kolom yang Anda ekstrak ( tail)
  3. rekatkan kolom ini ke file sumber Anda ( paste)

Contoh: file inpult sampel Anda:

abc 123    
abc 789  
bcd 456  
acb 135

Kemudian jalankan perintah berikut di terminal

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

Keluaran:

abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135

Struktur di balik solusi ini berbeda dari jawaban yang diberikan. Tidak perlu kondisi, loop, atau ekspresi reguler.

Hölderlin
sumber