Cosa fa% nelle stringhe di shell Linux?


28

Nella shell di Linux, cosa fa%, come in:

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

4
Ogni volta che lo cerco, di solito trovo la sezione giusta della pagina man di bash cercando %%o ##, dato che è memorabile e abbastanza raro da trovare rapidamente la sezione giusta. man bash /##
Peter Cordes,

3
@PeterCordes Lo ricordo sempre con "È 5%, quindi% è alla fine e quindi taglia dalla fine. Ed è # 5, quindi # è all'inizio e taglia dall'inizio." Ma a volte ho persino
confuso

2
@glglgl: su una tipica tastiera americana, #è immediatamente a sinistra di $, ed %è immediatamente a destra. Nessun mnemonico necessario --- basta guardare in basso. (Probabilmente questo è almeno in parte il motivo per cui quei simboli sono stati scelti.)
Kevin J. Chase,

@ KevinJ.Chase Non tutti in tutto il mondo hanno una tipica tastiera americana. Ma in effetti, su una tastiera tedesca, anche% ha ragione di $, che potrebbe essere un inizio per la memorizzazione.
glglgl,

Risposte:


29

Quando %viene utilizzato nel modello ${variable%substring}, restituisce il contenuto di variablecon la più breve occorrenza di substringeliminata dal retro di variable.

Questa funzione supporta modelli di caratteri jolly - ecco perché accetta la stella (asterisco) come sottostito per zero o più caratteri.

Va detto che questo è specifico di Bash - altre shell di Linux non contengono necessariamente questa funzione.

Se vuoi saperne di più sulla manipolazione delle stringhe in Bash, ti consiglio vivamente di leggere questa pagina. Tra le altre utili funzioni, ad esempio, spiega cosa fa %%:)

Modifica: ho dimenticato di menzionare che quando viene utilizzato nel modello $((variable%number))o $((variable1%$variable2))il %personaggio funzionerà come operatore modulo. DavidPostill ha collegamenti di documentazione più specifici nella sua risposta.

Quando %viene utilizzato in un contesto diverso, deve essere riconosciuto solo come carattere normale.


2
L'operatore supporta modelli di caratteri jolly , non espressioni regolari.
gardenhead

Come menzionato Gardenhead - supporta modelli glob, non espressioni regolari. Nell'espressione regolare una stella significa zero o più del carattere precedente.
Slebetman,

5
La guida che avete collegato a è molto non è raccomandato dalla maggior parte degli utenti di Exchange di Unix e Linux pila . Consiglio invece la guida di Wooledge Bash .
Carattere jolly

3
Gli operatori di rimozione prefisso e suffisso sono standard , quindi dovrebbero essere utilizzabili in qualsiasi shshell compatibile, non solo Bash. (anche se forse non in cshe simili).
ilkkachu,

1
Un altro contesto in cui %viene utilizzato è negli identificatori di formato per printf.
In pausa fino a nuovo avviso.

9

Manuale di riferimento di Bash: espansione dei parametri della shell

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

La parola viene espansa per produrre un modello proprio come nell'espansione del nome file. Se il modello corrisponde a una porzione finale del valore espanso del parametro , il risultato dell'espansione è il valore del parametro con il modello di corrispondenza più breve (il ‘%’caso) o il modello di corrispondenza più lungo (il ‘%%’caso) eliminato. Se il parametro è ‘@’o ‘*’,l'operazione di rimozione del motivo viene applicata a turno a ciascun parametro posizionale e l'espansione è l'elenco risultante. Se il parametro è una variabile di matrice sottoscritta con ‘@’ o‘*’, l'operazione di rimozione del motivo viene applicata a turno a ciascun membro dell'array e l'espansione è l'elenco risultante.


2
NB alcune espansioni di parametri tra cui% sono funzionalità posix supportate da molte shell.
Kojiro,

7

Sperimentando, trovo che una corrispondenza dopo% viene scartata, quando la stringa è racchiusa tra parentesi graffe (parentesi graffe).

Illustrare:

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

Ecco l'output:

abcd
abcd%
abcd
abcd

ab
abcd
ab
abcd
abcd%c*

7

Nella shell di Linux ( bash), cosa fa %?

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

In questo caso particolare, %è l' operatore di corrispondenza dei modelli (si noti che può anche essere un operatore modulo ).


Operatore di corrispondenza dei modelli

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

${var%$Pattern}Rimuovi dalla $varparte più corta di $Patternquella corrispondente alla parte posteriore di $var.

${var%%$Pattern}Rimuovi dalla $varparte più lunga di $Patternquella corrispondente alla parte posteriore di $var.

Esempio: corrispondenza dei modelli nella sostituzione dei parametri

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

Sostituzione parametri sorgente


Operatore Modulo

%

modulo o mod (restituisce il resto di un'operazione di divisione di un numero intero)

bash$ expr 5 % 3
2

5/3 = 1, con il resto 2

Operatori di fonte


Forse l'ho capito: questo è per cose del genere .*e lo %definisce non avido, mentre lo %%rende avido? Quindi, nell'esempio di rinomina, in realtà non importa se usarlo %o ( %%se si mv "$file" "${file%.*png.jpg}.jpg"noti il ​​*) usando %% rinominerebbe tutti i file in giusto .jpg, giusto?
Thomas Weller,

@ThomasWeller Penso che sia corretto. Ma non sono un esperto bash.
DavidPostill

Dire "Rimuovi ... la parte più breve di $Pattern" è errato poiché la variabile $Patternnon è definita nell'esempio, solo il testo "Pattern" viene rimosso da $varquando si fa ${var%Pattern}o ${var%%Pattern}. Forse questo è solo un errore di battitura, ma è l'ennesimo esempio di tldp.org che ha torto. BashGuide o Bash Hackers Wiki sono entrambi riferimenti molto meglio imho.
Giovanni B,

@JohnB Grazie. Entrambi i collegamenti sono stati aggiunti ai segnalibri. Ho corretto il testo nella risposta.
DavidPostill
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.