bash: як передавати аргументи командного рядка, що містять спеціальні символи


31

Я написав собі програму Linux, programяка потребує регулярного вираження в якості введення.

Я хочу викликати програму в bashоболонці і передати це регулярне вираження як аргумент командного рядка до програми (є й інші аргументи командного рядка). Схожий типовий регулярний вираз

[abc]\_[x|y]

На жаль, персонажі [, ]і |є особливими символами в bash. Таким чином, дзвоніть

program [abc]\_[x|y] anotheragument

не працює. Чи є спосіб передавати вираз, використовуючи якісь символи втечі або лапки тощо?

(Виклик program "[abc]\_[x|y] anotheragument"також не працює, оскільки він інтерпретує два аргументи як один.)

Відповіді:


27

Ви можете будь-який

  1. Уникайте кожного спеціального символу за допомогою нахилу (як на \[abc\]_\[x\|y\]) або
  2. Подвійне цитування всього аргументу (як у "[abc]_[x|y]").

EDIT: Як дехто зазначав, dobleqouting не перешкоджає розширенню змінних та заміні команд. Тому якщо ваш регулярний вираз містить щось, що може бути інтерпретоване bash як одне з них, використовуйте натомість окремі лапки .


4
У bash, подвійне цитування не обходить розширювані змінні "$HOME"чи параметри "${USER:-root}", підстановку команд у будь-якій формі "$(date)"або "`date`", арифметичне розширення "$((1 + 2))", розширення історії "!!"чи зворотній косої риски "\\". Використовуйте замість них одиничні лапки. Див. Man-сторінку посібника з bash, розділ під назвою "Цитування".
Flimm

25

Використовуйте одиничні цитати. Одиночні лапки гарантують, що жоден із символів не інтерпретується.

$ printf %s 'spaces  are  not  interpreted away
neither are new lines
nor variable names $TESTING
nor square brackets [TESTING]
nor pipe characters or redirection symbols | > <
nor the semicolon ;
nor backslashes \a \b \c \\
the only thing that does not work is the single quote itself
'

Якщо вам потрібно вставити одну цитату, є два рішення:

$ printf '%s\n' '[ Don'"'"'t worry, be happy! ]'
[ Don't worry, be happy! ]
$ printf '%s\n' '[ Don'\''t worry, be happy! ]'
[ Don't worry, be happy! ]

Право ти є. +1
антихрис

6

Пер man bash

Існує три механізми цитування: символ втечі , одиничні лапки та подвійні лапки.

Зворотний проріз, який не котирується ( \ ), є символом втечі . Він зберігає буквальне значення наступного символу, що випливає, за винятком <newline>. Якщо з'являється пара \ <newline>, а зворотна косої риски не є самою цитованою, \ <newline> трактується як продовження рядка (тобто він видаляється з вхідного потоку та фактично ігнорується).

Замикання символів в одиничних лапках зберігає буквальне значення кожного символу в лапках. Одиночна цитата може не виникати між окремими котируваннями, навіть коли передує зворотна косою рисою.

Замикання символів у подвійних лапках зберігає буквальне значення всіх символів у лапках, за винятком $ , ` , \ та, коли розширення історії включено ! . Символи $ і ` зберігають своє особливе значення в подвійних лапках. Зворотна косої риси зберігає своє особливе значення лише тоді, коли за нею слідує один із наступних символів: $ , ` , " , \ або <newline> . Подвійна котировка може бути цитована у подвійних лапках, попередньо її із зворотною косою рисою. Якщо це ввімкнено, розширення історії буде виконуватися, якщо не! З'явлення подвійних лапок уникне за допомогою зворотної косої риски. Нахил, що передує ! не видаляється.

Спеціальні параметри * і @ мають особливе значення у подвійних лапках (див. ПАРАМЕТРИ нижче).

Слова форми $ ' string " обробляються спеціально. Слово розширюється до рядка , а символи , що ухиляються від косої риски, замінюються відповідно до стандарту ANSI C. Послідовності втечі зворотного схилу, якщо вони є, декодуються наступним чином:

       \ А      оповіщення (дзвінок)
        \ ред      забій
        \ е 
       \ Е      маскуючою
        \ F      виду корму
        \ N      нового рядка
        \ г      повернення каретки
        \ т      горизонтальна вкладка
        \ v      вертикальна табуляція
        \\      зворотна коса
        \ "      апостроф
        \"      подвійні лапки
        \ NNN    восьми бітний символ, значення якого - вісімкове значення nnn
              (одна-три цифри)
       \ x HH    восьмирозрядний символ, значення якого - шістнадцяткове значення HH
              (одна або дві шістнадцяткові цифри)
       \ u HHHH символом Unicode (ISO / IEC 10646), значення якого
              шістнадцяткове значення HHHH (одна-чотири шістнадцяткові цифри)
        \ U HHHHHHHH
              символ Unicode (ISO / IEC 10646), значення якого
              шістнадцяткове значення HHHHHHHH (одна-вісім шістнадцяткових цифр)
        \ c x     контрольний x символ

Розширений результат одноцитований, як ніби знак долара не був.

Рядок з подвійним котируванням, який передує знаку долара ( $ " string " ), призведе до перекладу рядка відповідно до поточного локалу. Якщо поточний локал - C або POSIX , знак долара ігнорується. Якщо рядок переведено і замінено, заміна подвійно цитується.


2

Ви можете використовувати нахил ( \) перед спеціальними символами, щоб уникнути їх так:

john @ awesome: ~ # echo \ &
&

2

Хоча це може бути не корисним як регулярний вираз, деякі послідовності символів можуть інтерпретуватися як імена змінних Bash. Щоб цього не сталося і не було їх розширення, використовуйте одинарні замість подвійних лапок:

program '[abc]_[x|y]' anotherargument

Цитуйте кожен аргумент окремо (якщо вони потребують цитування), щоб вони трактувалися як незалежні аргументи. Ви також можете використовувати масиви в деяких випадках:

param_array=('[abc]_[x|y]' anotherargument)    # create an array
param_array+=(yetanother)     # append another element to the array
program "${param_array[@]}"   # use the array elements as arguments to program



0

Звідки береться візерунок? Виправлено це чи від користувача? Це користувач, який викликає скрипт у локальній системі, чи хтось віддалений?

Ви використовуєте лапки, щоб обернути дані, щоб оболонка не інтерпретувала їх. Є два варіанти:

  1. Подвійні котирування, які все ще дозволяють деяку інтерпретацію ($ розширення та "зворотній зв'язок")
  2. Одноцитати, які проходять все буквально

Оскільки $є дійсним символом у регулярних виразах (кінець рядка / буфер), ви, ймовірно, хочете використовувати одинарні лапки, щоб утримувати регулярний вираз, якщо ви не зберігаєте в змінній. Якщо ви приймаєте довільні дані від кого - то ненадійного, вам необхідно замінити 'з , '"'"'а потім загорнути в одинарних лапках.

Зауважте, що [abc]_[x|y]схоже на те, що ви хочете відповідати, xабо y, хоча він насправді відповідає одному з трьох символів xy|. Квадратні дужки відповідають символам всередині та лише -для діапазонів, а ^на початку - для заперечення. Отже, [abc]_(x|y)може бути те, що ви мали на увазі, а дужки - це символи, спеціальні для оболонки. Квадратні дужки не особливі для оболонки, це просто схоже на те, що вони є. Подвійні квадратні дужки [[ ... ]]спеціальні.


Це одна з найбільш правильних відповідей тут (особливо я ціную інструкцію щодо заміни 'на '"'"'), проте вона все ще не є правильною. [IS є спеціальним символом для оболонки, він використовується в wildcards під час розширення шляху (що оболонка робить для всього без котирування).
jpalecek

Це особливо в деяких контекстах, таких як підписка на змінну або для глобалізації, але ви все одно можете набрати, foo=a[b]а потім echo $fooі побачити, що рядок не потребував цитування. Ви маєте рацію, я був занадто короткий.
Філ П

Якщо вам не пощастило, abу поточному каталозі є файл , а тоді він fooбуде містити, abа не a[b]. Процитуйте свої квадратні дужки, люди.
clacke

(Для наочності: я цитую (як було зрозуміло в оригінальній відповіді, де я наштовхувався на цитування), і це є сторонне відхилення, на яке я звертаюся). Це твердження мене здивувало, тому я перевірив його. Це неправда в zsh або bash, але правда в BSD / bin / sh. Це проти POSIX і нестандартне поведінка, тому вам потрібно буде запропонувати цитати, щоб впоратися з цим. У zsh ви також можете setopt glob_assignвключити таку поведінку, тому цитування є найбезпечнішою відповіддю.
Phil P
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.