Apa yang dilakukan% dalam string shell Linux?

28

Di Linux shell, apa yang dilakukan%, seperti pada:

for file in *.png.jpg; do
  mv "$file" "${file%.png.jpg}.jpg"
done
Nissim Nanach
sumber
4
Setiap kali saya mencari ini, saya biasanya menemukan bagian kanan halaman bash man dengan mencari %%atau ##, karena itu cukup mudah diingat dan langka untuk menemukan bagian yang tepat dengan cepat. man bash /##
Peter Cordes
3
@PeterCordes Saya selalu ingat ini dengan "Ini 5%, jadi% di akhir dan dengan demikian memotong dari akhir. Dan itu # 5, jadi # di awal dan memotong dari awal." Tetapi kadang-kadang saya bahkan mencampuradukkan yang ini ...
glglgl
2
@glglgl: Pada papan ketik khas Amerika Serikat, #langsung ke kiri $, dan %langsung ke kanan. Tidak perlu mnemonik --- lihat saja ke bawah. (Itu mungkin setidaknya bagian dari mengapa simbol-simbol itu dipilih.)
Kevin J. Chase
@ KevinJ.Chase Tidak semua orang di seluruh dunia memiliki keyboard khas Amerika Serikat. Tapi tentu saja, pada keyboard Jerman,% benar $ juga, itu bisa menjadi awal untuk memoizing.
glglgl

Jawaban:

29

Ketika %digunakan dalam pola ${variable%substring}itu akan mengembalikan konten variabledengan kejadian terpendek substringdihapus dari belakang variable.

Fungsi ini mendukung pola wildcard - itulah sebabnya ia menerima bintang (tanda bintang) sebagai subtitle untuk nol atau lebih karakter.

Harus disebutkan bahwa ini khusus untuk Bash - shell linux lain tidak perlu mengandung fungsi ini.

Jika Anda ingin mempelajari lebih lanjut tentang manipulasi string di Bash, saya sangat menyarankan membaca halaman ini . Di antara fungsi praktis lainnya - misalnya - menjelaskan apa yang %%harus dilakukan :)

Edit: Saya lupa menyebutkan bahwa ketika itu digunakan dalam pola $((variable%number))atau $((variable1%$variable2))yang %karakter akan berfungsi sebagai operator modulo. DavidPostill memiliki tautan dokumentasi yang lebih spesifik dalam jawabannya.

Ketika %digunakan dalam konteks yang berbeda, itu harus dikenali sebagai karakter biasa saja.

Marek Rost
sumber
2
Operator mendukung pola wildcard , bukan ekspresi reguler.
gardenhead
Seperti gardenhead yang disebutkan - mendukung pola glob, bukan ekspresi reguler. Dalam ekspresi reguler, bintang berarti nol atau lebih dari karakter sebelumnya.
slebetman
5
Panduan yang Anda tautkan sangat tidak direkomendasikan oleh sebagian besar pengguna pertukaran pertukaran Unix & Linux . Saya merekomendasikan Woolash Bash Guide sebagai gantinya.
Wildcard
3
Awalan dan akhiran menghapus operator adalah standar , sehingga mereka harus dapat digunakan dalam shshell yang kompatibel, tidak hanya Bash. (Meskipun mungkin tidak dalam cshdan sejenisnya).
ilkkachu
1
Konteks lain yang %digunakan adalah penentu format untuk printf.
Dijeda sampai pemberitahuan lebih lanjut.
9

Manual Referensi Bash: Ekspansi Parameter Shell

${parameter%word}
${parameter%%word}

The Kata diperluas untuk menghasilkan pola seperti dalam ekspansi nama file. Jika pola cocok dengan bagian tambahan dari nilai parameter yang diperluas , maka hasil ekspansi adalah nilai parameter dengan pola pencocokan terpendek ( ‘%’kasing) atau pola pencocokan terpanjang ( ‘%%’kasing) dihapus. Jika parameter adalah ‘@’atau ‘*’,operasi penghapusan pola diterapkan untuk setiap parameter posisional pada gilirannya, dan ekspansi adalah daftar yang dihasilkan. Jika parameter adalah variabel array yang disubkripsikan dengan ‘@’ atau‘*’, operasi penghapusan pola diterapkan pada setiap anggota array secara bergantian, dan ekspansi adalah daftar yang dihasilkan.

Steven
sumber
2
NB beberapa perluasan parameter termasuk% adalah fitur posix yang didukung banyak shell.
kojiro
7

Dengan bereksperimen, saya menemukan bahwa kecocokan setelah% dibuang, ketika string tertutup dalam kurung keriting (kurung kurawal).

Menggambarkan:

touch abcd         # Create file abcd

for file in ab*; do
 echo $file        # echoes the filename
 echo $file%       # echoes the filename plus "%"
 echo ${file%}     # echoes the filename
 echo "${file%}"   # echoes the filename
 echo
 echo "${file%c*}" # Discard anything after % matching c*
 echo "${file%*}"  # * is not greedy
 echo ${file%c*}   # Without quotes works too
 echo "${file%c}"  # No match after %, no effect
 echo $file%c*     # Without {} fails
done

Berikut hasilnya:

abcd
abcd%
abcd
abcd

ab
abcd
ab
abcd
abcd%c*
Nissim Nanach
sumber
7

Di Linux shell ( bash), apa fungsinya %?

for file in *.png.jpg; do
  mv "$file" "${file%.png.jpg}.jpg"
done

Dalam kasus ini, %adalah pencocokan pola operator (perhatikan juga bisa menjadi modulo operator).


Operator Pencocokan Pola

$ {var% $ Pattern}, $ {var %% $ Pattern}

${var%$Pattern}Hapus dari $varbagian terpendek $Patternyang cocok dengan bagian belakang $var.

${var%%$Pattern}Hapus dari $varbagian terpanjang $Patternyang cocok dengan bagian belakang $var.

Contoh: Pencocokan pola dalam substitusi parameter

#!/bin/bash
# patt-matching.sh

# Pattern matching  using the # ## % %% parameter substitution operators.

var1=abcd12345abc6789
pattern1=a*c  # * (wild card) matches everything between a - c.

echo
echo "var1 = $var1"           # abcd12345abc6789
echo "var1 = ${var1}"         # abcd12345abc6789
                              # (alternate form)
echo "Number of characters in ${var1} = ${#var1}"
echo

echo "pattern1 = $pattern1"   # a*c  (everything between 'a' and 'c')
echo "--------------"
echo '${var1#$pattern1}  =' "${var1#$pattern1}"    #         d12345abc6789
# Shortest possible match, strips out first 3 characters  abcd12345abc6789
#                                     ^^^^^               |-|
echo '${var1##$pattern1} =' "${var1##$pattern1}"   #                  6789      
# Longest possible match, strips out first 12 characters  abcd12345abc6789
#                                    ^^^^^                |----------|

echo; echo; echo

pattern2=b*9            # everything between 'b' and '9'
echo "var1 = $var1"     # Still  abcd12345abc6789
echo
echo "pattern2 = $pattern2"
echo "--------------"
echo '${var1%pattern2}  =' "${var1%$pattern2}"     #     abcd12345a
# Shortest possible match, strips out last 6 characters  abcd12345abc6789
#                                     ^^^^                         |----|
echo '${var1%%pattern2} =' "${var1%%$pattern2}"    #     a
# Longest possible match, strips out last 12 characters  abcd12345abc6789
#                                    ^^^^                 |-------------|

# Remember, # and ## work from the left end (beginning) of string,
#           % and %% work from the right end.

echo

exit 0

Substitusi Parameter Sumber


Operator Modulo

%

modulo, atau mod (mengembalikan sisa operasi pembagian integer)

bash$ expr 5 % 3
2

5/3 = 1, dengan sisanya 2

Operator Sumber

DavidPostill
sumber
Mungkin saya mengerti: ini untuk hal-hal seperti .*dan %mendefinisikannya sebagai tidak serakah sedangkan %%membuatnya serakah? Jadi sebenarnya dalam contoh ganti nama itu tidak masalah apakah akan menggunakan %atau %%tetapi jika mv "$file" "${file%.*png.jpg}.jpg"(perhatikan *) menggunakan %% akan mengubah nama semua file menjadi adil .jpg, kan?
Thomas Weller
@ ThomasWeller saya pikir itu benar. Tapi aku bukan ahli bash.
DavidPostill
Mengatakan "Hapus ... bagian terpendek dari $Pattern" salah karena variabel $Patterntidak didefinisikan dalam contoh, hanya teks "Pola" yang dihapus dari $varsaat melakukan ${var%Pattern}atau ${var%%Pattern}. Mungkin ini hanya salah ketik, tapi ini contoh lain kesalahan tldp.org. BashGuide atau Bash Hackers Wiki keduanya adalah referensi yang jauh lebih baik.
John B
@ JohnB Terima kasih. Kedua tautan itu ditandai. Saya sudah mengoreksi teks dalam jawaban.
DavidPostill