Co% robi w łańcuchach powłoki Linuxa?

28

W powłoce Linux, co robi%, jak w:

for file in *.png.jpg; do
  mv "$file" "${file%.png.jpg}.jpg"
done
Nissim Nanach
źródło
4
Za każdym razem, gdy to sprawdzam, zwykle znajduję odpowiednią sekcję strony podręcznika bash, wyszukując %%lub ##, ponieważ jest to niezapomniane i wystarczająco rzadkie, aby szybko znaleźć odpowiednią sekcję. man bash /##
Peter Cordes
3
@PeterCordes Zawsze pamiętam to przez „To 5%, więc% jest na końcu, a zatem wycina od końca. I to jest # 5, więc # jest na początku i cięcia od początku”. Ale czasem nawet mylę ten…
glglgl
2
@glglgl: Na typowej klawiaturze USA #znajduje się bezpośrednio po lewej stronie $i %bezpośrednio po prawej stronie. Nie potrzeba mnemonika - wystarczy spojrzeć w dół. (To prawdopodobnie przynajmniej część tego, dlaczego te symbole zostały wybrane.)
Kevin J. Chase
@ KevinJ.Chase Nie każdy na świecie ma typową klawiaturę w USA. Rzeczywiście, na niemieckiej klawiaturze% ma również wartość $, co może być początkiem do zapamiętywania.
glglgl

Odpowiedzi:

29

Gdy %zostanie użyty we wzorcu ${variable%substring}, zwróci zawartość variablez najkrótszym wystąpieniem substringusuniętym z tyłu variable.

Ta funkcja obsługuje wzory wieloznaczne - dlatego przyjmuje gwiazdkę (gwiazdkę) jako substytut zerowej lub większej liczby znaków.

Należy wspomnieć, że jest to specyficzne dla Bash - inne powłoki linuksowe niekoniecznie zawierają tę funkcję.

Jeśli chcesz dowiedzieć się więcej na temat manipulacji ciągami w Bash, gorąco polecam przeczytanie tej strony. Wśród innych przydatnych funkcji to - na przykład - wyjaśnia, co robi %%:)

EDIT: Zapomniałem wspomnieć, że gdy jest stosowany w strukturze $((variable%number))lub postać będzie funkcjonować jako operator modulo. DavidPostill ma w swojej odpowiedzi bardziej szczegółowe linki do dokumentacji.$((variable1%$variable2))%

Gdy %jest używany w innym kontekście, powinien być rozpoznawany tylko jako zwykły znak.

Marek Rost
źródło
2
Operator obsługuje wzory wieloznaczne , a nie wyrażenia regularne.
ogrodnik
Jak wspomniano o ogrodniku - obsługuje globalne wzory, a nie wyrażenia regularne. W wyrażeniu regularnym gwiazda oznacza zero lub więcej poprzedniego znaku.
slebetman
5
Przewodnik masz związana jest bardzo nie zalecane przez większość użytkowników wymiany UNIX'a & Linux stos . Zamiast tego polecam Wooledge Bash Guide .
Wildcard
3
Operatory usuwające prefiks i sufiks są standardowe , więc powinny być użyteczne w dowolnej shkompatybilnej powłoce, nie tylko w Bash. (choć być może nie cshi tym podobne).
ilkkachu
1
Innym kontekstem, w którym %jest używany, są specyfikatory formatu dla printf.
Wstrzymano do odwołania.
9

Podręcznik referencyjny Bash: Rozszerzanie parametrów powłoki

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

Słowo jest interpretowane tworząc wzorzec, tak samo jak przy rozwijaniu nazw plików. Jeśli wzorzec pasuje do końcowej części rozwiniętej wartości parametru , wynikiem rozszerzenia jest wartość parametru z usuniętym najkrótszym pasującym wzorcem ( ‘%’przypadek) lub najdłuższym pasującym wzorcem ( ‘%%’przypadek). Jeśli parametr ma wartość ‘@’lub ‘*’,operacja usuwania wzorca jest stosowana do każdego parametru pozycyjnego po kolei, a rozwinięcie jest listą wynikową. Jeśli parametr jest zmienną tablicową indeksowaną za pomocą ‘@’ lub‘*’, operacja usuwania wzoru jest kolejno stosowana do każdego elementu tablicy, a rozwinięcie jest listą wynikową.

Steven
źródło
2
Uwaga: niektóre rozszerzenia parametrów, w tym%, są elementami posiksowymi obsługiwanymi przez wiele powłok.
kojiro
7

Eksperymentując, stwierdzam, że dopasowanie po% jest odrzucane, gdy łańcuch jest ujęty w nawiasy klamrowe (nawiasy klamrowe).

Ilustrować:

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

Oto wynik:

abcd
abcd%
abcd
abcd

ab
abcd
ab
abcd
abcd%c*
Nissim Nanach
źródło
7

bashCo robi Linux shell ( ) %?

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

W tym konkretnym przypadku, %to dopasowywanie wzorca operator (uwaga to może być również modulo operator).


Operator dopasowywania wzorców

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

${var%$Pattern}Usuń z $varnajkrótszej części $Patternpasującej do tylnego końca $var.

${var%%$Pattern}Usuń z $varnajdłuższej części $Patternpasującej do tylnego końca $var.

Przykład: Dopasowywanie wzorców w podstawianiu parametrów

#!/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

Zmiana parametru źródła


Operator Modulo

%

modulo lub mod (zwraca pozostałą część operacji dzielenia liczb całkowitych)

bash$ expr 5 % 3
2

5/3 = 1, z resztą 2

Operatorzy źródła

DavidPostill
źródło
Może mam to: to jest dla takich rzeczy .*i %określa, że ​​jest nie chciwy, a %%czyni to chciwym? Więc faktycznie w przykładzie przemianowania nie ma znaczenia, czy do użytku %lub %%jeśli jednak były mv "$file" "${file%.*png.jpg}.jpg"(uwaga *) przy użyciu %% by zmienić nazwy wszystkich plików po prostu .jpg, prawda?
Thomas Weller,
@ThomasWeller Myślę, że to prawda. Ale nie jestem ekspertem od bashów.
DavidPostill
Mówienie „Usuń ... najkrótszą część $Pattern” jest błędne, ponieważ zmienna $Patternnie jest zdefiniowana w przykładzie, tylko tekst „Wzór” jest usuwany $varpodczas wykonywania ${var%Pattern}lub ${var%%Pattern}. Może to tylko literówka, ale to kolejny przykład pomyłki tldp.org. Wiki BashGuide lub Bash Hackers są znacznie lepszymi referencjami imho.
John B
@JohnB Dzięki. Oba linki są oznaczone zakładkami. Poprawiłem tekst w odpowiedzi.
DavidPostill