menghapus karakter pertama dan terakhir dari setiap baris dari baris perintah

8

Saya mencoba untuk menghapus karakter pertama dan terakhir dari setiap baris dalam file teks dan menyimpan versi terpotong yang dihasilkan dalam file baru. Adakah yang punya ide tentang bagaimana melakukannya secara efisien menggunakan awkatau program / perintah linux lainnya khusus untuk file besar?

input.txt

(s,2,4,5,6)
"s,1,5,5,2"
{z,0,4,5,3}
[y,2,4,5,5]
(y,4,4,5,7)
(r,20,4,5,7)
(e,9,4,5,2)

Output.txt yang diharapkan

s,2,4,5,6
s,1,5,5,2
z,0,4,5,3
y,2,4,5,5
y,4,4,5,79
r,20,4,5,7
e,9,4,5,2
pacodelumberg
sumber

Jawaban:

14

Cara lain hanya untuk itu:

rev input | cut -c2- | rev | cut -c2-

(Catatan: dengan GNU cut, hanya berfungsi untuk karakter yang hanya terbuat dari satu byte (seperti pada contoh Anda)).

Drake Clarris
sumber
Bagus! Ini secara signifikan lebih cepat daripada solusi sed dan awk yang diusulkan sejauh ini.
Gilles 'SANGAT berhenti menjadi jahat'
Saya mengusulkan jawaban ini untuk orang-orang yang takut sintaks sed / awk / regex, tetapi tidak akan membayangkan itu lebih cepat, terutama untuk file besar, dengan tiga pipa dan melewati seluruh konten melalui masing-masing. Akan berpikir sed atau awk membaca baris pada suatu waktu akan lebih efisien untuk file besar.
Drake Clarris
3
Tebak itulah yang 40 + tahun optimasi banyak utilitas * nix ini akan membuat Anda!
Drake Clarris
@Gilles, lebih cepat ke GNU di lokal utf8 untuk beberapa bentuk input, dan itu tergantung apakah Anda mempertimbangkan waktu jam dinding, atau waktu CPU. ssedatau toolchest Heirloom seddapat mencapai kinerja yang lebih baik.
Stéphane Chazelas
@Gilles Tidak ada entri MAN untuk rev di Solaris 5.10. Saya akhirnya menggunakansed
ayrton_senna
10

Sesuai pertanyaan Anda hapus kata terakhir dan pertama dari file input seperti di bawah ini:

sed 's/.$//; s/^.//' inputfile
Rahul Patil
sumber
Akan keren jika Anda dapat membandingkan ini terhadap solusi lain s/.\(.*\).$/\1/,. Mungkin lebih cepat karena tidak menggunakan referensi, dan pertanyaan itu menyebutkan "file besar".
l0b0
4
@ l0b0 Saya diuji dengan time yes | head -n 10000000 | COMMAND >/dev/null. Saya mendapatkan rev input | cut -c2- | rev | cut -c2-→ 0.14s, sed 's,.\(.*\).$,\1,'→ 3.38s; awk '{print substr($0,2,length()-2);}'→ 3,50s; sed 's/.$//; s/^.//'→ 5.09s.
Gilles 'SANGAT berhenti menjadi jahat'
@Gilles +1 Itu seharusnya menjadi jawaban.
l0b0
2
@ Gilles, itu kalimat yang sangat pendek. Saya menemukan bahwa untuk 30 karakter garis lebar, solusi @ RahulPatil adalah 3 kali lebih cepat dengan GNU sed daripada @ juampa. Juga. sed 's/.\(.*\)./\1/'tampaknya lebih cepat daripada sed 's/^.\(.*\).$/\1/'(GNU sed lagi). Selain itu, kinerjanya tergantung pada lokal (interpretasi karakter) dan sedimplementasinya (dalam hal itu, sed dari heirloom toolchest jauh lebih cepat daripada sed GNU).
Stéphane Chazelas
5

Ada banyak kemungkinan, seperti biasa

sed 's,.\(.*\).$,\1,g' your_file

Penjelasan

  • , - pembatas sed, bisa berupa karakter lain juga, mengingat itu lolos di mana pun dibutuhkan.
  • . Cocokkan satu karakter
  • \(.*\) - Kelompokkan bagian yang tersisa, dan ini disimpan untuk diambil lebih lanjut.
  • . Cocokkan satu karakter lagi
  • $ - Akhir baris
  • \1 - Keluarkan teks yang cocok dengan grup di atas
  • g ganti secara global di telepon.
jpmuc
sumber
2
Mengapa g? hanya akan ada satu pertandingan per baris.
njsg
Perhatikan bahwa itu tidak akan menghapus apa pun dari garis yang memiliki kurang dari 2 karakter.
Stéphane Chazelas
3

Anda juga dapat melakukannya dengan awkjika Anda mau

awk '{print substr($0,2,length()-2);}' input.txt > output.txt
StrongBad
sumber
2
tr -d '()[]{}"' < your_file

Ini harus bekerja juga. Itu juga "menerjemahkan" masing-masing karakter menjadi tidak ada (hapus).

The downside adalah bahwa itu akan menghapus mereka jika mereka bukan karakter pertama / terakhir juga. Itu juga akan melewatkan karakter akhir apa pun yang tidak Anda cantumkan di ()[....

Mark Nichols
sumber