Что означает «$ {line # * 'Caused By'}»! = «$ Line» в сценарии оболочки?

tail -f /var/log/squid/access.log | ( c=0; pl() { echo $c; c=0; }; trap pl SIGHUP; while read a; do (( c=c+1 )); done ) & ( trap 'kill $! ; exit' SIGINT; trap '' SIGHUP; while true; do kill -HUP $! ; sleep 1; done)
7
13.02.2018, 21:06
2 ответа

${line#*'Caused By'}— это конкретный пример подстановки переменных ${parameter#word}(, как это написано в руководстве bash, а также в стандарте POSIX для оболочки sh).

В ${parameter#word}шаблон wordбудет удален из начала значения $parameter.Он называется «Удалить шаблон наименьшего префикса», потому что он удалит самую короткую совпадающую строку префикса, которая соответствует шаблону вword##вместо #. Он удалит самый длинный . ] соответствующая строка префикса ).

В этом конкретном примере строкаCaused by(и все, что предшествует ей, благодаря *), если она существует, удаляется из значения $line. Одинарные кавычки вокруг строки избыточны.

Сравнивая результат подстановки со значением самой переменной, тест определяет, содержит ли значение $lineтекст Caused by, и печатает Yes, если содержит.

Это имеет тот же эффект, что и

if [[ "$line" == *'Caused by'* ]]; then
    echo 'Yes'
fi

в bash, ksh93или zsh, или

case "$line" in
    *'Caused by'*) echo 'Yes'
esac

в любой оболочке sh.


Цикл в вопросе считывает «строки» из стандартного ввода. См. вопрос "Понимание "IFS= чтение -r строки" для обсуждения этого.

12
27.01.2020, 20:14

La acción (o la ejecución en este caso )siempre habla más alto, así que veamos qué hace este script cuando se ejecuta (disculpe la libertad de hacer que la salida sea más detallada):

while read -r line
do 
  if [ "${line#*'Caused by'}" != "$line" ]; then
    echo "Line contains string Caused by"
  else
    echo "Line does not contain string Caused by"
  fi
done

Input: String with Caused by
Output: Line contains string Caused by
Input: Just a normal string
Output: Line does not contain string Caused by

La coincidencia de patrones utilizada en este script "${line#*'Caused by'}reemplaza toda la cadena (debido al comodín*)desde el principio hasta el final deCausado poren la línea ingresada y luego se compara con el parámetro original $linepara ver si son iguales o no. En pocas palabras, todo lo que hace es comprobar si la línea contiene la cadena Causado por . Finalmente, imprime La ​​línea contiene una cadena Causado por si la línea contiene Causado por .

Ahora,algunas palabras sobre la expansión de parámetros de shell para el formato ${parameter#word}con algunos ejemplos:

If the pattern matches the beginning of the value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern (the "#'' case) or the longest matching pattern (the "##'' case) deleted.

$ test=aabbcc
$ echo ${test#*bb}                                                                    
$ cc

$ test=aabbcc
$ echo ${test#a*b}                                                                    
$ bcc

Un ejemplo del formato de patrón coincidente más largo:

$ test=aabbcc
$ echo ${test##a*b}                                                                     
$ cc

Referencia:man bash:${parameter#word}

3
27.01.2020, 20:14

Теги

Похожие вопросы