Saya memiliki file yang terlihat seperti ini:
AE United Arab Emirates
AG Antigua & Barbuda
AN Netherlands Antilles
AS American Samoa
BA Bosnia and Herzegovina
BF Burkina Faso
BN Brunei Darussalam
Dan saya ingin membalik pesanan, pertama-tama mencetak semuanya kecuali $ 1 lalu $ 1:
United Arab Emirates AE
Bagaimana saya bisa melakukan trik "semuanya kecuali bidang 1"?
Jawaban:
Penetapan
$1
berfungsi tetapi akan meninggalkan ruang utama:awk '{first = $1; $1 = ""; print $0, first; }'
Anda juga dapat menemukan jumlah kolom dalam
NF
dan menggunakannya dalam satu lingkaran.sumber
awk {'first = $1; $1=""; print $0'}|sed 's/^ //g'
$1=""
sisakan ruang seperti yang disebutkan Ben Jackson, jadi gunakanfor
loop:Jadi jika string Anda adalah "satu dua tiga", hasilnya akan menjadi:
dua
tiga
Jika Anda menginginkan hasil dalam satu baris, Anda dapat melakukan hal berikut:
Ini akan memberi Anda: "dua tiga"
sumber
awk '{for(i=2;i<=NF;i++){ printf("%s",( (i>2) ? OFS : "" ) $i) } ; print ;}'
which: print fields 2 to NF, tambahkan Output Field Separator seperlunya (yaitu, kecuali sebelum $ 2). Cetakan terakhir menambahkan baris baru terakhir untuk mengakhiri pencetakan baris saat ini. Yang itu akan berfungsi jika Anda mengubah FS / OFS (yaitu, tidak selalu menjadi "ruang")Gunakan
cut
perintah dengan--complement
opsi:sumber
echo a b c | cut -d' ' -f 2-
adalah alternatifMungkin cara paling ringkas:
Penjelasan:
$(NF+1)=$1
: Generator kolom terakhir "baru".$1=""
: Setel bidang pertama yang asli ke nolsub(FS,"")
: Setelah dua tindakan pertama{$(NF+1)=$1;$1=""}
singkirkan pemisah bidang pertama dengan menggunakan sub. Hasil cetak terakhir tersirat.sumber
Hapus bidang pertama dan pemisah, dan cetak hasilnya (
7
adalah nilai bukan nol jadi mencetak $ 0).sumber
1
? Saya ingin tahu penggunaan pola ini dan ingin memahaminya. Terima kasih!Menyetel bidang pertama untuk
""
menyisakan satu salinanOFS
di awal$0
. Dengan asumsi ituOFS
hanya satu karakter (secara default, itu adalah satu spasi), kita dapat menghapusnya dengansubstr($0, 2)
. Kemudian kami menambahkan salinan yang disimpan dari$1
.sumber
Jika Anda terbuka untuk solusi Perl ...
adalah solusi sederhana dengan pemisah input / output satu spasi, yang menghasilkan:
Yang berikut ini sedikit lebih kompleks
dan mengasumsikan bahwa pemisah input / output adalah dua spasi:
Opsi baris perintah ini digunakan:
-n
memutar di sekitar setiap baris file input, jangan mencetak setiap baris secara otomatis-l
menghapus baris baru sebelum diproses, dan menambahkannya kembali setelahnya-a
mode autosplit - memisahkan baris input ke dalam larik @F. Secara default, pemisahan di spasi kosong-F
pengubah pemisahan otomatis, dalam contoh ini dibagi menjadi '' (dua spasi)-e
jalankan kode perl berikut@F
adalah larik kata di setiap baris, diindeks mulai dengan 0$#F
adalah jumlah kata dalam@F
@F[1..$#F]
potongan larik elemen 1 sampai elemen terakhir@F[1..$#F,0]
adalah irisan larik elemen 1 sampai elemen terakhir ditambah elemen 0sumber
Pemisah bidang di gawk (setidaknya) bisa berupa string serta karakter (bisa juga berupa regex). Jika data Anda konsisten, ini akan berfungsi:
Itu dua spasi di antara tanda kutip ganda.
sumber
awk '{ tmp = $1; sub(/^[^ ]+ +/, ""); print $0, tmp }'
sumber
Mari pindahkan semua record ke record berikutnya dan atur yang terakhir sebagai yang pertama:
Penjelasan
a=$1
simpan nilai pertama ke dalam variabel sementara.for (i=2; i<=NF; i++) $(i-1)=$i
simpan nilai bidang ke-N ke dalam bidang (N-1).$NF=a
simpan nilai pertama ($1
) ke dalam bidang terakhir.{}1
Kondisi benar untuk makeawk
melakukan tindakan default:{print $0}
.Dengan cara ini, jika Anda kebetulan memiliki pemisah bidang lain, hasilnya juga bagus:
sumber
Tusukan pertama tampaknya berhasil untuk kasus khusus Anda.
sumber
Pilihan 1
Ada solusi yang berfungsi dengan beberapa versi awk:
Penjelasan:
Hasil:
Namun itu mungkin gagal dengan versi awk yang lebih lama.
pilihan 2
Itu adalah:
Perhatikan bahwa yang perlu dihapus adalah OFS, bukan FS. Garis akan dihitung ulang saat bidang $ 1 ditentukan. Itu mengubah semua proses FS menjadi salah satu OFS.
Tetapi bahkan opsi itu masih gagal dengan beberapa pembatas, seperti yang ditunjukkan secara jelas dengan mengubah OFS:
Baris itu akan menampilkan:
Itu menunjukkan bahwa run dari FS sedang diubah menjadi salah satu OFS.
Satu-satunya cara untuk menghindarinya adalah dengan menghindari penghitungan ulang bidang.
Salah satu fungsi yang dapat menghindari penghitungan ulang adalah sub.
Bidang pertama dapat diambil gambarnya, lalu dihapus dari $ 0 dengan sub, dan kemudian keduanya dicetak ulang.
Pilihan 3
Bahkan jika kita mengubah FS, OFS dan / atau menambahkan lebih banyak pembatas, itu berhasil.
Jika file input diubah menjadi:
Dan perintah berubah menjadi:
Outputnya adalah (masih mempertahankan pembatas):
Perintah dapat diperluas ke beberapa bidang, tetapi hanya dengan awks modern dan dengan opsi --re-interval active. Perintah ini pada file asli:
Akan menampilkan ini:
sumber
Jika Anda terbuka untuk solusi Perl lain:
sumber
Ada pilihan sed juga ...
Dijelaskan ...
Lebih jelasnya dijelaskan ...
sumber
Namun cara lain ...
... ini menggabungkan kembali bidang 2 melalui NF dengan FS dan mengeluarkan satu baris per baris masukan
Saya menggunakan ini dengan git untuk melihat file apa yang telah dimodifikasi di direktori kerja saya:
sumber
Cara lain dan mudah menggunakan perintah cat
sumber