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


31

Eu escrevi para mim mesmo um programa linux programque precisa de uma expressão regular como entrada.

Quero chamar o programa no bashshell e passar essa expressão regular como um argumento de linha de comando para o programa (também existem outros argumentos de linha de comando). Uma expressão regular típica parece

[abc]\_[x|y]

Infelizmente, os personagens [, ]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.?

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

Respostas:


27

Você também pode

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

EDIT: Como alguns salientaram, 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 deles, use aspas simples .


4
No bash, as aspas duplas não ignoram variáveis "$HOME"ou parâmetros em expansão "${USER:-root}", substituem comandos sob forma "$(date)"ou "`date`"expansão aritmética "$((1 + 2))", expansão de histórico "!!"ou escape de barra invertida "\\". Use aspas simples. Veja a página de manual do manual do bash, a seção intitulada "Citações".
Flimm

25

Use aspas simples. 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 cotaçã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! ]

Você está certo. +1
antichris

6

Por man bash

Existem três mecanismos de citação: o caractere de escape , aspas simples e aspas duplas.

Uma barra invertida não citada ( \ ) é o caractere de escape . Ele preserva o valor literal do próximo caractere a seguir, com exceção de <newline>. Se um par \ <newline> aparecer e a barra invertida não estiver entre aspas, o \ <newline> será tratado como uma continuação de linha (ou seja, será removido do fluxo de entrada e efetivamente ignorado).

Incluir caracteres entre aspas simples preserva o valor literal de cada caractere dentro das aspas. Uma aspas simples pode não ocorrer entre aspas simples, mesmo quando precedida por uma barra invertida.

A inclusão de caracteres entre aspas duplas preserva o valor literal de todos os caracteres entre aspas, com exceção de $ , ` , \ e, quando a expansão do histórico estiver ativada ,! . Os caracteres $ e ` mantêm seu significado especial entre aspas duplas. A barra invertida retém seu significado especial somente quando seguido por um dos seguintes caracteres: $ , ` , " , \ ou <newline> . Uma citação dupla pode ser citada entre aspas duplas precedendo-a com uma barra invertida. Se ativado, expansão do histórico será realizada a menos que! aparecer entre aspas duplas é escapado usando uma barra invertida. A barra invertida que precede o ! não é removido.

Os parâmetros especiais * e @ têm um significado especial entre aspas duplas (consulte PARÂMETROS abaixo).

Palavras da forma $ ' string ' são tratadas especialmente. A palavra se expande para cadeia , com caracteres de escape com barra invertida substituídos conforme especificado pelo padrão ANSI C. Seqüências de escape de barra invertida, se presentes, são decodificadas da seguinte maneira:

       \ um      alerta (sino)
        \ b      retrocesso
        \ e 
       \ E      um caractere de escapar
        \ f      alimentação de forma
        \ n      nova linha
        \ r      retorno do carro
        \ t      horizontal guia
        \ v      patilha vertical
        \\      barra invertida
        \'      apóstrofo
        \"      dobrar citação
        \ nnn    o caractere de oito bits cujo valor é o valor octal nnn
              (um a três dígitos)
       \ x HH    o caractere de oito bits cujo valor é o valor hexadecimal HH
              (um ou dois dígitos hexadecimais)
       \ u HHHH o caractere Unicode (ISO / IEC 10646) cujo valor é
              o valor hexadecimal HHHH (um a quatro dígitos hexadecimais)
        \ U HHHHHHHH
              o caractere Unicode (ISO / IEC 10646) cujo valor é
              o valor hexadecimal HHHHHHHH (um a oito dígitos hexadecimais)
        \ c x     um caractere de controle x

O resultado expandido é de aspas simples, como se o cifrão não estivesse presente.

Uma sequência de aspas duplas precedida por um sinal de dólar ( $ " string " ) fará com que a string seja traduzida de acordo com o código de idioma atual. Se o código do idioma atual for C ou POSIX , o cifrão será ignorado. Se a sequência for traduzida e substituída, a substituição será citada duas vezes.


2

Você pode usar uma barra invertida ( \) na frente de caracteres especiais para escapar deles da seguinte maneira:

john @ awesome: ~ # eco \ &
&

2

Embora possa não ser útil como uma expressão regular, algumas seqüências de caracteres podem ser interpretadas como nomes de variáveis ​​do Bash. Para evitar que isso ocorra e evite expandi-los, use aspas simples em vez de aspas duplas:

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

Cite cada argumento separadamente (se precisar citar) 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

1
program "[abc]_[x|y]"
program "[abc]_[x|y]" anotherargument

0

Escapá-los deve funcionar bem:

  programm \[abc\]_\[x\|y\]

0

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

Você usa aspas para agrupar os dados e impedir que o shell os 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 deseja usar aspas simples para armazenar o regexp, a menos que esteja armazenando uma variável. Se você está tomando os dados arbitrária de alguém não confiável, você vai precisar para substituir 'com '"'"'e em seguida, enrole em aspas simples.

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


Esta é uma das respostas mais corretas aqui (eu aprecio especialmente as instruções para substituí- las 'por '"'"'), no entanto, ainda não está correta. [É um caractere especial para o shell, é usado em curingas ao fazer a expansão de caminho (que o shell faz para tudo que não é citado).
precisa saber é o seguinte

É especial em alguns contextos, como assinatura variável ou globbing, mas você ainda pode digitar foo=a[b]e depois echo $foover que a sequência não precisa ser citada. Você está certo, eu fui muito breve.
Phil P

Se você é azarado, há um arquivo abno diretório atual e fooconterá ab, em vez de a[b]. Cite seus colchetes, pessoal.
Clacke

(Para maior clareza: cito (como a resposta original deixou claro, onde eu estava pressionando para citar), e este é um descarrilamento lateral que estou abordando). Essa afirmação me surpreendeu, então eu a testei. Não é verdade no zsh ou no bash, mas no BSD / bin / sh. Isso é contra o POSIX e é um comportamento não padrão; portanto, você precisará citar para lidar com isso. No zsh, você também pode setopt glob_assignhabilitar esse comportamento, portanto, citar é a resposta mais segura.
Phil P
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.