bash: como passar argumentos de linha de comando contendo caracteres especiais

25

Eu mesmo escrevi um programa em linux program que precisa de uma expressão regular como entrada.

Eu quero chamar o programa no shell bash e passar essa expressão regular como um argumento de linha de comando para o programa (há também outros argumentos de linha de comando). Uma expressão regular típica se parece com

[abc]\_[x|y]

Infelizmente, os caracteres [ , ] e | são caracteres especiais em bash . Assim, chamando

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

não funciona. Existe uma maneira de passar a expressão usando algum tipo de caractere de escape ou aspas, etc.?

(Chamar program "[abc]\_[x|y] anotheragument" também não está funcionando, porque interpreta os dois argumentos como um.)

    
por Christian 14.07.2010 / 14:51

8 respostas

22

Você pode

  1. Escape de cada símbolo especial com uma barra invertida (como em \[abc\]_\[x\|y\] ) ou
  2. Doublequote o argumento inteiro (como em "[abc]_[x|y]" ).

EDITAR: Como alguns apontaram, o dobleqouting não impede a expansão de variáveis nem a substituição de comandos. Portanto, se o seu regex contiver algo que possa ser interpretado pelo bash como um desses, use aspas simples em seu lugar.

    
por 14.07.2010 / 14:59
23

Use aspas simples. As aspas simples garantem que nenhum dos caracteres seja interpretado.

$ 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
'

Existem duas soluções se você precisar incorporar uma única citação:

$ 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! ]
    
por 21.10.2011 / 14:19
6

Por man bash

There are three quoting mechanisms: the escape character, single quotes, and double quotes.

A non-quoted backslash (\) is the escape character. It preserves the literal value of the next character that follows, with the exception of <newline>. If a \<newline> pair appears, and the backslash is not itself quoted, the \<newline> is treated as a line continuation (that is, it is removed from the input stream and effectively ignored).

Enclosing characters in single quotes preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.

Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, ', \, and, when history expansion is enabled, !. The characters $ and ' retain their special meaning within double quotes. The backslash retains its special meaning only when followed by one of the following characters: $, ', ", \, or <newline>. A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an ! appearing in double quotes is escaped using a backslash. The backslash preceding the ! is not removed.

The special parameters * and @ have special meaning when in double quotes (see PARAMETERS below).

Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard. Backslash escape sequences, if present, are decoded as follows:

       \a     alert (bell)
       \b     backspace
       \e
       \E     an escape character
       \f     form feed
       \n     new line
       \r     carriage return
       \t     horizontal tab
       \v     vertical tab
       \     backslash
       \'     single quote
       \"     double quote
       \nnn   the eight-bit character whose value is the octal value nnn
              (one to three digits)
       \xHH   the eight-bit character whose value is the hexadecimal value HH
              (one or two hex digits)
       \uHHHH the Unicode (ISO/IEC 10646) character whose value is
              the hexadecimal value HHHH (one to four hex digits)
       \UHHHHHHHH
              the Unicode (ISO/IEC 10646) character whose value is
              the hexadecimal value HHHHHHHH (one to eight hex digits)
       \cx    a control-x character

The expanded result is single-quoted, as if the dollar sign had not been present.

A double-quoted string preceded by a dollar sign ($"string") will cause the string to be translated according to the current locale. If the current locale is C or POSIX, the dollar sign is ignored. If the string is translated and replaced, the replacement is double-quoted.

    
por 15.07.2010 / 08:09
2

Você pode usar uma barra invertida ( \ ) na frente dos caracteres especiais para evitá-los da seguinte forma:

john@awesome:~ # echo \&
&
    
por 14.07.2010 / 14:57
2

Embora possa não ser útil como um regex, algumas seqüências de caracteres podem ser interpretadas como nomes de variáveis Bash. Para evitar que isso ocorra e evitar que eles sejam expandidos, use aspas simples em vez de aspas duplas:

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

Cite cada argumento separadamente (se eles precisarem de citações) para que eles sejam interpretados como argumentos independentes. Você também pode usar matrizes em alguns casos:

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
    
por 15.07.2010 / 04:11
1
program "[abc]_[x|y]"
program "[abc]_[x|y]" anotherargument
    
por 14.07.2010 / 14:56
0

Escapá-los deve funcionar bem:

  programm \[abc\]_\[x\|y\]
    
por 14.07.2010 / 14:57
0

De onde vem o padrão? É fixo ou de um usuário? É o usuário que está invocando o script no sistema local ou alguém remoto?

Você usa aspas para agrupar os dados para impedir que o shell o interprete. Existem duas opções:

  1. Aspas duplas, que ainda permitem alguma interpretação ($ expand e 'backticks')
  2. Aspas simples, que passam tudo literalmente

Como $ é um caractere válido em regexps (fim-de-linha / buffer), você provavelmente desejará usar aspas simples para conter o regexp, a menos que esteja armazenando em uma variável. Se você estiver usando dados arbitrários de alguém não confiável, será necessário substituir ' por '"'"' e, em seguida, incluir aspas simples.

Observe que [abc]_[x|y] parece que você deseja corresponder x ou y , enquanto na verdade corresponde a um dos três caracteres xy| . Os colchetes correspondem aos caracteres dentro e somente - para intervalos e um ^ no início para negação. Então, [abc]_(x|y) pode ser o que você quis dizer, e os parênteses são os caracteres especiais para shell. Parênteses quadrados são não especiais para shell, apenas parece que são. Parênteses duplos [[ ... ]] são especiais.

    
por 15.07.2010 / 09:18