Saya ingin menghapus karakter terakhir dari sebuah string, saya mencoba skrip kecil ini:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
tetapi mencetak "lkj", apa yang saya lakukan salah?
Saya ingin menghapus karakter terakhir dari sebuah string, saya mencoba skrip kecil ini:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
tetapi mencetak "lkj", apa yang saya lakukan salah?
Jawaban:
Dalam shell POSIX, sintaksnya ${t:-2}
berarti sesuatu yang berbeda - itu berkembang ke nilai t
jika t
diatur dan bukan nol, dan sebaliknya ke nilai 2
. Untuk memangkas satu karakter dengan ekspansi parameter, sintaks yang mungkin Anda inginkan adalah${t%?}
Perhatikan bahwa dalam ksh93
, bash
atau zsh
, ${t:(-2)}
atau ${t: -2}
(perhatikan spasi) adalah legal sebagai perluasan substring tetapi mungkin bukan yang Anda inginkan, karena mereka mengembalikan substring mulai dari posisi 2 karakter dari akhir (yaitu menghilangkan karakter pertamai
dari string ijk
).
Lihat bagian Perluasan Parameter Shell pada Bash Reference Manual untuk info lebih lanjut:
${parameter%word}
menghapus pencocokan pola sufiks terpendek word
- lihat bagian Ekspansi Parameterman bash
Dengan bash
4.2 dan di atasnya, Anda dapat melakukan:
${var::-1}
Contoh:
$ a=123
$ echo "${a::-1}"
12
Perhatikan bahwa untuk yang lebih lama bash
(misalnya, bash 3.2.5
pada OS X), Anda harus meninggalkan spasi di antara dan setelah titik dua:
${var: : -1}
bash
versi 4.2-alpha dan di atasnya, sayang sekali versi yang saya akses sebelumnya. : - /
${var:offset:lenght}
ditambahkan hanya dalam bash 4.2
. Mungkin OSX menambahkan tambalannya sendiri bash
.
untuk menghapus n
karakter terakhir dari garis yang tidak menggunakan sed
OR awk
:
> echo lkj | rev | cut -c (n+1)- | rev
jadi misalnya Anda dapat menghapus karakter terakhir one character
menggunakan ini:
> echo lkj | rev | cut -c 2- | rev
> lk
dari rev
manpage:
DESKRIPSI
Utilitas rev menyalin file yang ditentukan ke output standar, membalik urutan karakter di setiap baris. Jika tidak ada file yang ditentukan, input standar dibaca.
MEMPERBARUI:
jika Anda tidak tahu panjang tali, coba:
$ x="lkj"
$ echo "${x%?}"
lk
Menggunakan sed itu harus secepat
sed 's/.$//'
Kemudian gema tunggal Anda echo ljk | sed 's/.$//'
.
Dengan menggunakan ini, string 1-line dapat berukuran berapa saja.
Beberapa opsi tergantung pada shell:
t=${t%?}
t=`expr " $t" : ' \(.*\).'`
t=${t[1,-2]}
t=${t:0:-1}
t=${t:0:${#t}-1}
t=${t/%?}
t=${t/~(E).$/}
@ {t=$1} ~~ $t *?
Perhatikan bahwa sementara semua seharusnya menghapus karakter terakhir , Anda akan menemukan bahwa beberapa implementasi (yang tidak mendukung karakter multi-byte) malah menghapus byte terakhir (sehingga kemungkinan akan merusak karakter terakhir jika multi-byte) ).
The expr
varian mengasumsikan $t
tidak berakhir di lebih dari satu karakter baris baru. Ini juga akan mengembalikan status keluar non-nol jika string yang dihasilkan berakhir menjadi 0
(atau 000
atau bahkan -0
dengan beberapa implementasi). Itu juga bisa memberikan hasil yang tidak terduga jika string berisi karakter yang tidak valid.
t=${t%?}
bukan Bourne tetapi Anda tidak akan menemukan shell Bourne saat ini. ${t%?}
tidak bekerja di semua yang lain sekalipun.
fish
sedang dalam proses. 2.3.0 yang memperkenalkan string
builtin tidak dirilis pada saat tanya jawab. Dengan versi yang saya uji, Anda perlu string replace -r '(?s).\z' '' -- $t
(dan saya berharap mereka ingin mengubahnya, mereka harus mengubah flag yang mereka berikan ke PCRE) atau yang lebih berbelit-belit. Itu juga berurusan dengan buruk dengan karakter baris baru, dan saya tahu mereka berencana untuk mengubah itu juga.
Jawaban yang paling portabel, dan terpendek, hampir pasti:
${t%?}
Ini berfungsi di bash, sh, ash, dash, busybox / ash, zsh, ksh, dll.
Ini bekerja dengan menggunakan ekspansi parameter shell old-school. Secara khusus, %
menentukan untuk menghapus akhiran pencocokan terkecil dari parameter t
yang cocok dengan pola glob ?
(yaitu: karakter apa saja).
Lihat "Hapus Pola Sufiks Terkecil" di sini untuk penjelasan (lebih banyak) lebih rinci dan lebih banyak latar belakang. Lihat juga dokumen untuk shell Anda (misalnya:) di man bash
bawah "ekspansi parameter".
Sebagai catatan, jika Anda ingin menghapus karakter pertama , Anda akan menggunakan ${t#?}
, karena #
kecocokan dari depan string (awalan) alih-alih dari belakang (akhiran).
Juga diperhatikan adalah bahwa kedua %
dan #
memiliki %%
dan ##
versi yang cocok dengan terpanjang versi pola yang diberikan bukannya terpendek. Keduanya ${t%%?}
dan ${t##?}
akan melakukan hal yang sama sebagai operator tunggal mereka dalam hal ini (jadi jangan tambahkan karakter tambahan yang tidak berguna). Ini karena ?
pola yang diberikan hanya cocok dengan satu karakter. Gabungkan *
dengan beberapa non-wildcard dan hal-hal menjadi lebih menarik dengan %%
dan ##
.
Memahami ekspansi parameter, atau setidaknya mengetahui tentang keberadaannya dan mengetahui cara mencarinya, sangat berguna untuk menulis dan menguraikan skrip shell dari banyak rasa. Ekspansi parameter sering terlihat seperti voodoo shell misterius bagi banyak orang karena ... well ... mereka adalah voodoo shell misterius (meskipun cukup baik didokumentasikan jika Anda tahu untuk mencari "ekspansi parameter"). Pasti bagus untuk ada di sabuk alat saat Anda terjebak dalam cangkang.
t=lkj
echo ${t:0:${#t}-1}
Anda mendapatkan substring dari 0 hingga panjang string -1. Namun perlu dicatat bahwa substraksi ini khusus untuk bash, dan tidak akan berfungsi pada shell lainnya.
Misalnya, bahkan dash
tidak dapat menguraikan
echo ${t:0:$(expr ${#t} - 1)}
Misalnya, di Ubuntu, /bin/sh
adalahdash
Anda juga dapat menggunakan head
untuk mencetak semua kecuali karakter terakhir.
$ s='i am a string'
$ news=$(echo -n $s | head -c -1)
$ echo $news
i am a strin
Namun sayangnya beberapa versi head
tidak menyertakan -
opsi unggulan . Ini adalah kasus untuk head
yang datang dengan OS X.
Hanya untuk melengkapi beberapa kemungkinan penggunaan bash murni:
#!/bin/bash
# Testing substring removal
STR="Exemple string with trailing whitespace "
echo "'$STR'"
echo "Removed trailing whitespace: '${STR:0:${#STR}-1}'"
echo "Removed trailing whitespace: '${STR/%\ /}'"
Sintaks pertama mengambil substring dari string, sintaksnya adalah
Untuk yang kedua, perhatikan tanda, yang berarti 'dari ujung garis' dan sintaksnya adalah
${STRING:OFFSET:LENGTH}
%
${STRING/PATTERN/SUBSTITUTION}
Dan berikut adalah dua bentuk yang lebih pendek dari yang disebutkan di atas
echo "Removed trailing whitespace: '${STR::-1}'"
echo "Removed trailing whitespace: '${STR%\ }'"
Di sini perhatikan lagi %
tanda, yang berarti 'Hapus (yaitu, ganti dengan' ') pola cocok terpendek (di sini diwakili oleh ruang melarikan diri ' \ ' dari ujung PARAMETER - di sini bernama STR