Saya tahu bahwa cut
perintah dapat mencetak n
karakter pertama dari suatu string tetapi bagaimana cara memilih n
karakter terakhir ?
Jika saya memiliki string dengan jumlah karakter variabel, bagaimana saya bisa mencetak hanya tiga karakter terakhir dari string. misalnya.
Output "tidak terbatas" yang dibutuhkan adalah "ted" "987654" output yang dibutuhkan adalah "654" "123456789" output yang dibutuhkan adalah "789"
text-processing
cut
pengembaraan
sumber
sumber
grep -o '.\{3\}$'
echo "unlimited" | python -c "print raw_input()[-3:]"
"echo unlimited" | java -jar EnterpriseWordTrimmer.jar
, tapi saya tidak berpikir itu benar-benar perlu untuk membawa bahasa yang lebih berat untuk manipulasi karakter.java -server -Xms300M -Xmx3G -XX:+UseParallelGC -cp /path/to/all/the/jars/ -Dinput.interactive=false -Dinput.pipe=true -Dconfig.file=/path/to/config/last-three-letters.cfg -jar ...
grep -o -P '.{0,3}$'
akan mencetak 3 karakter terakhir walaupun garis tersebut memiliki kurang dari 3 karakter.-P
menghindari harus melarikan diri dari kawat gigi.Menjaga agar tetap sederhana - ekor
Kita tidak perlu ekspresi reguler, atau lebih dari satu proses, hanya untuk menghitung karakter.
Perintah
tail
, yang sering digunakan untuk menampilkan baris terakhir file, memiliki opsi-c
(--bytes
), yang tampaknya menjadi alat yang tepat untuk ini:(Ketika Anda berada di shell, masuk akal untuk menggunakan metode seperti dalam jawaban mikeserv, karena menyimpan memulai proses untuk
tail
.)Karakter Unicode sungguhan?
Sekarang, Anda meminta tiga karakter terakhir ; Bukan itu yang diberikan jawaban ini: menghasilkan tiga byte terakhir !
Selama setiap karakter adalah satu byte,
tail -c
hanya berfungsi. Jadi itu bisa digunakan jika set karakternya adalahASCII
,ISO 8859-1
atau varian.Jika Anda memiliki input Unicode, seperti dalam
UTF-8
format umum , hasilnya salah:Dalam contoh ini, menggunakan
UTF-8
, karakter yunani alfa, beta dan gamma panjangnya dua byte:Opsi
-m
setidaknya dapat menghitung karakter unicode yang sebenarnya:Ok, jadi 6 byte terakhir akan memberi kita 3 karakter terakhir:
Jadi,
tail
tidak mendukung penanganan karakter umum, dan bahkan tidak mencoba (lihat di bawah): Ini menangani garis ukuran variabel, tetapi tidak ada karakter ukuran variabel.Mari kita begini:
tail
tepat untuk struktur masalah untuk dipecahkan, tetapi salah untuk jenis data.GNU coreutils
Melihat lebih jauh, ternyata engkau coreutils GNU, koleksi alat dasar seperti
sed
,ls
,tail
dancut
, belum sepenuhnya internasionalisasi. Yang terutama tentang mendukung Unicode.Misalnya,
cut
akan menjadi kandidat yang baik untuk digunakan alih-alih mengikuti di sini untuk dukungan karakter; Itu memang memiliki opsi untuk bekerja pada byte atau karakter,-c
(--bytes
) dan-m
(--chars
);Hanya itu
-m
/--chars
adalah, sebagai versicut (GNU coreutils) 8.21
2013,tidak dilaksanakan!
Dari
info cut
:Lihat juga jawaban ini untuk Tidak dapat menggunakan `cut -c` (` --characters`) dengan UTF-8? .
sumber
cut
Tampaknya hanya solusi Anda dan glenn jackman yang berbasis itu.tail
harus berurusan dengan byte, dan bukan karakter. Saya pernah membuat tambalan untuk menambahkan opsi baru untuk juga memilih karakter, tapi saya percaya itu tidak pernah digabung: - /tail -c3 -n10 /var/log/syslog
tail -c3 -n10 /var/log/syslog
meminta 10 baris terakhir, dan itu berhasil untuk saya. Anda menggunakan opsi-c3
, dan setelah itu opsi yang bertentangan-n10
. Opsi selanjutnya diprioritaskan.Jika teks Anda dalam variabel shell disebut
STRING
, Anda bisa melakukan ini dalambash
,zsh
ataumksh
shell:Atau
yang juga memiliki manfaat untuk bekerja dengan ksh93 dari mana sintaks itu berasal.
Intinya adalah bahwa
:
harus dipisahkan dari-
, jika tidak menjadi${var:-default}
operator cangkang Bourne.Sintaks yang setara dalam
zsh
atauyash
shell adalah:sumber
${STRING:(-3):3}
(menentukan bidang panjang ),${STRING: -3}
(dengan spasi antara:
dan-
), atau${STRING: -3:3}
.3
agak diperdebatkan karena meminta "tiga karakter dari ketiga dari karakter terakhir, inklusif" yang kebetulan merupakan operasi yang identik dalam istilah praktis untuk "Semua karakter ke depan dari yang ketiga dari yang terakhir , inklusif ".Menggunakan
awk
:sumber
Jika string ada dalam variabel yang bisa Anda lakukan:
Itu menghilangkan tiga karakter terakhir dari nilai
$var
like:... dan kemudian strip dari kepala
$var
segalanya tetapi apa yang baru saja dilucuti seperti:Metode ini memiliki kelebihan dan kekurangannya. Sisi baiknya adalah sepenuhnya POSIX-portable dan dapat digunakan di semua shell modern. Juga, jika
$var
tidak mengandung setidaknya tiga karakter tidak ada tetapi garis akhir trailing\n
dicetak. Kemudian lagi, jika Anda ingin mencetaknya, Anda perlu langkah tambahan seperti:Dengan cara
$last3
itu hanya akan kosong jika$var
mengandung 3 byte atau lebih sedikit. Dan$var
hanya diganti$last3
jika$last3
kosong atauunset
- dan kita tahu itu bukanunset
karena kita hanya mengaturnya.sumber
printf
string format Anda ?${VARNAME:(-3)}
(menganggapbash
)?bash
halnya pada shell lain yang mengklaim kompatibilitas POSIX.csh
adalah tidak di antara , modern POSIX-kompatibel kerang saya sebutkan di sini, sayangnya. Spec POSIX-shell dimodelkan setelahksh
, yang memodelkan dirinya sendiri setelah kombinasi keduanyacsh
dan shell gaya Bourne tradisional.ksh
menggabungkan keduacsh
fungsi kontrol pekerjaan yang sangat baik dan pengalihan i / o gaya Bourne lama. Itu juga menambahkan beberapa hal - seperti konsep manipulasi string yang saya tunjukkan di atas. Ini kemungkinan tidak akan berhasil dalam tradisionalcsh
sejauh yang saya tahu, saya minta maaf untuk mengatakan.Anda dapat melakukan ini, tetapi ini sedikit ... berlebihan:
sumber
Solusi anti peluru untuk utf-8 strings:
Atau gunakan:
untuk mencegah penanganan data yang cacat.
Contoh:
Keluaran sesuatu seperti ini:
Tidak tergantung pada pengaturan lokal (yaitu bekerja dengan
LC_ALL=C
).Bash
,sed
,grep
,awk
,rev
Membutuhkan sesuatu seperti ini:LC_ALL=en_US.UTF-8
Solusi umum:
Anda dapat mendeteksi pengodean dengan uchardet . Lihat juga proyek terkait .
Anda dapat mendekode / menyandi dengan Encode di Perl, codec dengan Python 2.7
Contoh :
Ekstrak tiga karakter terakhir dari utf-16le string dan konversi karakter-karakter ini ke utf-8
Lihat juga: perlunitut , Python 2 Unicode HOWTO
sumber
echo
Apakah sumber antipeluru Anda?decode/encode
adalah sumber antipeluru saya. Bersihkan jawaban saya.LC_ALL=C
karena itu pengaturan yang sangat "bodoh", tetapi mungkin rusak ketika Anda mencoba untuk meneruskan string UTF-8 ke SHIFT-5, atau string SHIFT-5 ke KOI8, dll.perl -CAO -e 'print substr($ARGV[0], -3)'
berfungsi dengan baik.A
elemen @ARGV diharapkan berupa string yang dikodekan dalam UTF-8,O
STDOUT akan berada di UTF-8.utf8_str
Bagaimana dengan menggunakan "expr" atau "rev"?
Jawaban serupa dengan yang diberikan oleh @ G-Man :
expr "$yourstring" : '.*\(...\)$'
Ini memiliki kelemahan yang sama dari solusi grep.Trik yang terkenal adalah menggabungkan "potong" dengan "putaran":
echo "$yourstring" | rev | cut -n 1-3 | rev
sumber
rev
solusi terlihat banyak seperti glenn jackman iniDapatkan ukuran string dengan:
Kemudian dapatkan substring dari n karakter terakhir:
Sebagai contoh:
akan memberi:
sumber
tail -n 1 revisi.log | awk '{print substr ($ 0, 0, length ($ 0) - (length ($ 0) -13))}'
Jika Anda ingin mencetak tiga belas karakter pertama dari awal
sumber
printf tidak akan berfungsi jika string memiliki spasi di dalamnya.
Kode di bawah ini untuk string dengan spasi
sumber
printf
tidak berhasil, maka Anda melakukan sesuatu yang sangat salah.printf $str
(bukanprintf "$str"
atauprintf '%s' "$str"
). Dan, ya,printf $str
adalah sangat salah. (echo -n $str
tidak jauh lebih baik.)