Bagaimana saya bisa menghapus kata ke-5 dari setiap baris dalam file?

13

Saya ingin menghapus kata ke-5 dari setiap baris dalam sebuah file.

Konten file saat ini:

File is not updated or and will be removed  
System will shut down f within 10 seconds  
Please save your work 55 or copy to other location  
Kindly cooperate with us D  

Output yang diharapkan:

File is not updated and will be removed  
System will shut down within 10 seconds  
Please save your work or copy to other location  
Kindly cooperate with us
pmaipmui
sumber

Jawaban:

31

Bagaimana dengan cut:

$ cut -d' ' -f1-4,6- file.txt 
File is not updated and will be removed  
System will shut down within 10 seconds  
Please save your work or copy to other location  
Kindly cooperate with us
  • -d' ' menetapkan pembatas sebagai ruang

  • -f1-4,6- memilih bidang pertama hingga ke 4 (kata), meninggalkan bidang ke-5 dan kemudian melanjutkan pencetakan dari urutan ke-6 ke yang lainnya.

heemayl
sumber
11

Solusi dengan cut:

cut -d ' ' -f1-4 -f6- FILE
fd0
sumber
Beberapa -ftidak didukung di cut(GNU) saya setidaknya ..
heemayl
Didukung dalam pemotongan BSD tapi saya suka respons Anda lebih baik daripada saya.
fd0
1
Jika itu GNU dipotong, Anda mendapatkan --complementbendera untuk menyederhanakan hal: cut --complement -d ' ' -f5. Ingatlah untuk mengarahkan kembali output ke file baru, lalu mvke yang asli.
Toby Speight
6

awk: hapus bidang ke-5

awk '{for (i=5; i<NF; i++) $i = $(i+1); NF--};1' file

Jika Anda ingin menyimpan file di tempat: /programming//q/16529716/7552

Anda bisa menghapus isi bidang ke-5, tetapi itu meninggalkan 2 pemisah bidang keluaran berturut-turut:

awk '{$5 = ""};1' file
glenn jackman
sumber
peringatan di sini adalah bahwa mengubah nilai bidang apa pun dalam awk memiliki efek samping menulis ulang seluruh "$ 0" dengan hanya 1 pemisah antara masing-masing bidang. harus diperhitungkan jika Anda ingin menjaga keberpihakan (kecuali gnu awk memiliki pilihan untuk menghindari ini? awk / nawk reguler akan menghitung ulang $ 0)
Olivier Dulac
Dalam kedua kasus Anda memformat ulang garis dengan pemisah tunggal . Jika ada 2 spasi atau spasi + tab di pemisah, hasilnya adalah satu ruang di tempat. Ini untungnya OK untuk sebagian besar teks.
NeronLeVelu
4

Dengan POSIX sed:

sed -e 's/[^[:alnum:]_][[:alnum:]_][[:alnum:]_]*//4' <file
cuonglm
sumber
mengapa membatasi kelas untuk: alnum: _ dan bukan yang lain :blank:atau dulu :space:?
NeronLeVelu
@NeronLeVelu: Itu tergantung pada bagaimana Anda mendefinisikan apa yang membuat kata.
cuonglm
@ mikeserv; Tangkapan bagus! Saya memperbarui jawaban saya.
cuonglm
Untuk apa \(kelompok tangkap \)?
mikeserv
@ mikeserv: salah ketik saya, saya baru saja mencoba beberapa cara untuk mempertahankan pembatas.
cuonglm
2

Glenn menawarkan solusi yang setara dengan

awk '{$ 5 = ""; cetak file }

Seperti yang dia dan orang lain tunjukkan, ini

  1. strip whitespace terkemuka dan tertinggal dari setiap baris,
  2. kompres setiap string spasi putih (spasi dan / atau tab) menjadi satu ruang, dan
  3. menyisakan dua spasi antara kata keempat dan enam.

Retasan untuk memperbaiki masalah ketiga adalah

awk '{$ 5 = ""; cetak} ' file | sed 's / / /'

Ini masih akan menyisakan satu atau lebih ruang tambahan di akhir setiap baris yang memuat lima atau lebih sedikit kata. Jika Anda dapat mengidentifikasi kata yang tidak akan pernah muncul di input,

awk '{$ 5 = "unicorn"; cetak file } | sed 's / * unicorn //'

akan menangani bahkan itu (tetapi masih menyisakan masalah 1 dan 2).

Scott
sumber
2
 sed 's/^\(\([[:blank:]]*[^[:blank:]]\{1,\}\)\{4\}\)[[:blank:]]*[^[:blank:]]*/\1/' YourFile > Output.txt
  • posix sed berdasarkan pemisah spasi / tab (kelas meta [: kosong:]])
  • simpan spasi berikut setelah kata ke-5 tetapi hapus kata sebelumnya

Yang lebih kuat (sed mengambil pola terpanjang mungkin dan pola dengan *bisa kehilangan pemisahan atau kata dalam versi pertama) tetapi versi yang sedikit lebih lama

sed 's/^\([[:blank:]]*\([^[:blank:]]\{1,\}[[:blank:]]\{1,\}\)\{4\}\[^[:blank:]]\{1,\}/\1/' YourFile > Output.txt
NeronLeVelu
sumber
1
sed 's/[^[:blank:]]*//5'
mikeserv
@ mikeserv, ini akan membuat kedua pemisah di sekitarnya, sed 's/[[:blank:]*[^[:blank:]]*//5'lebih baik. Poin yang sangat bagus. Saya curiga bahwa sed mengambil masing-masing char sebagai entitas tetapi dibutuhkan pola unbreaked terbesar sebagai entitas
NeronLeVelu
sed 's/[[:blank:]][^[:blank:]]*//4'akan menghapus seluruhnya bidang ke-5.
mikeserv
@ mikeserv Dengan asumsi tidak ada ruang mulai di telepon (seperti dalam sampel)
NeronLeVelu
Dalam hal ini, ya, saya pikir Anda benar. Biasanya hal seperti itu akan menjadi bidang nol dan perilakunya akan benar. Dalam hal ini Anda harus melakukan seperti @cuonglm lakukan dan memastikan Anda referensi kata setiap kali seperti sed 's/[[:blank:]][^[:blank:]][^[:blank:]]*//4', atau, w / GNU / BSD / toybox seds: sed -E 's/[[:blank:]][^[:blank:]]+//4'.
mikeserv
1

Perl.

perl -ne 'print $_ =~ /^(\w+ +\w+ +\w+ +\w+ +)\w+ (.*)/,"\n"' file
steve
sumber
1

Kemungkinan lain, dengan asumsi GNU dipotong:

cut -d' ' -f5 --complement file.txt
Trauma Digital
sumber
-1

Menggunakan Perl> 5.10 (dan berhasil mengeluarkan semua baris: 0)): -

perl -nE '/^((\w+ +){4})\w+ *(.*)/; say $1.$3' file
Medlock Perlman
sumber