bash: come passare argomenti della riga di comando contenenti caratteri speciali


31

Mi sono scritto un programma Linux programche ha bisogno di un'espressione regolare come input.

Voglio chiamare il programma nella bashshell e passare quell'espressione regolare come argomento della riga di comando al programma (ci sono anche altri argomenti della riga di comando). Sembra una tipica espressione regolare

[abc]\_[x|y]

Purtroppo i personaggi [, ]e |sono personaggi speciali in bash. Quindi, chiamando

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

non funziona C'è un modo per passare l'espressione usando una sorta di caratteri di escape o virgolette ecc.?

(Anche la chiamata program "[abc]\_[x|y] anotheragument"non funziona, perché interpreta i due argomenti come uno.)

Risposte:


27

Puoi farlo

  1. Sfuggire a ogni singolo simbolo speciale con una barra rovesciata (come in \[abc\]_\[x\|y\]) o
  2. Quota doppia l'intero argomento (come in "[abc]_[x|y]").

EDIT: come alcuni hanno sottolineato, dobleqouting non impedisce l'espansione variabile né la sostituzione dei comandi. Pertanto se il tuo regex contiene qualcosa che può essere interpretato da bash come uno di quelli, usa invece virgolette singole .


4
In bash, le virgolette doppie non aggirano l'espansione di variabili "$HOME"o parametri "${USER:-root}", la sostituzione dei comandi in una forma "$(date)"o "`date`", l'espansione aritmetica, l'espansione della "$((1 + 2))"cronologia "!!"o l'escape di barra rovesciata "\\". Utilizzare invece virgolette singole. Vedi la pagina man del manuale di bash, la sezione intitolata "Citando".
Flimm,

25

Usa virgolette singole. Le virgolette singole assicurano che nessuno dei caratteri sia interpretato.

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

Esistono due soluzioni se è necessario incorporare una singola citazione:

$ 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! ]

Hai ragione. +1
antichris

6

Per man bash

Esistono tre meccanismi di quotazione: il carattere di escape , virgolette singole e virgolette doppie.

Una barra rovesciata non quotata ( \ ) è il carattere di escape . Conserva il valore letterale del carattere successivo che segue, ad eccezione di <newline>. Se viene visualizzata una coppia \ <newline> e la barra rovesciata non viene citata, la \ <newline> viene trattata come una continuazione di riga (ovvero viene rimossa dal flusso di input e effettivamente ignorata).

Racchiudere i caratteri tra virgolette singole conserva il valore letterale di ciascun carattere tra virgolette. Tra virgolette singole non può verificarsi una virgoletta, anche se preceduta da una barra rovesciata.

Racchiudere i caratteri tra virgolette doppie conserva il valore letterale di tutti i caratteri tra virgolette, ad eccezione di $ , ` , \ e, quando l'espansione della cronologia è abilitata ,! . I caratteri $ e ` mantengono il loro significato speciale tra virgolette doppie. La barra rovesciata conserva il suo significato speciale solo se seguita da uno dei seguenti caratteri: $ , ` , " , \ o <newline> . Una virgoletta doppia può essere citata tra virgolette precedenti precedendola con una barra rovesciata. Se abilitata, l'espansione della cronologia sarà eseguito a meno che un! apparire tra virgolette viene evitato usando una barra rovesciata. La barra rovesciata che precede il ! non viene rimosso.

I parametri speciali * e @ hanno un significato speciale tra virgolette (vedi PARAMETRI di seguito).

Le parole del modulo $ ' stringa ' sono trattate in modo speciale. La parola si espande in stringa , con i caratteri con escape backslash sostituiti come specificato dallo standard ANSI C. Le sequenze di escape barra rovesciata, se presenti, sono decodificate come segue:

       \ a      alert (campana)
        \ b      backspace
        \ e 
       \ E      un carattere di escape
        \ f      feed feed
        \ n      nuova riga
        \ r      ritorno a capo
        \ t      scheda orizzontale
        \ v      scheda verticale
        \\      barra rovesciata
        \ '      virgoletta singola
        \ "      virgoletta doppia
        \ nnn    il carattere a otto bit il cui valore è il valore ottale nnn
              (da una a tre cifre)
       \ x HH    il carattere a otto bit il cui valore è il valore esadecimale HH
              (una o due cifre esadecimali)
       \ uHHHH il carattere Unicode (ISO / IEC 10646) il cui valore è
              il valore esadecimale HHHH (da una a quattro cifre esadecimali)
        \ U HHHHHHHH
              il carattere Unicode (ISO / IEC 10646) il cui valore è
              il valore esadecimale HHHHHHHH (da una a otto cifre esadecimali)
        \ c x     un carattere control- x

Il risultato espanso è tra virgolette singole, come se il segno del dollaro non fosse stato presente.

Una stringa tra virgolette preceduta da un simbolo di dollaro ( $ " stringa " ) farà sì che la stringa venga tradotta in base alle impostazioni internazionali correnti. Se la locale corrente è C o POSIX , il simbolo del dollaro viene ignorato. Se la stringa viene tradotta e sostituita, la sostituzione viene racchiusa tra virgolette.


2

Puoi usare una barra rovesciata ( \) davanti a caratteri speciali per evitarli in questo modo:

john @ awesome: ~ # echo \ &
&

2

Anche se potrebbe non essere utile come regex, alcune sequenze di caratteri possono essere interpretate come nomi di variabili Bash. Per evitare che ciò accada ed evitare che vengano espansi, utilizzare virgolette singole anziché doppie:

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

Cita ogni argomento separatamente (se hanno bisogno di un preventivo) in modo che vengano interpretati come argomenti indipendenti. È inoltre possibile utilizzare le matrici in alcuni casi:

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

Scapparli dovrebbe funzionare bene:

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

0

Da dove viene lo schema? È stato risolto o da un utente? È l'utente che sta invocando lo script sul sistema locale o qualcuno remoto?

Utilizzare le virgolette per racchiudere i dati in modo da impedire alla shell di interpretarli. Esistono due opzioni:

  1. Virgolette doppie, che consentono ancora qualche interpretazione ($ expand e `backticks`)
  2. Virgolette singole, che passano letteralmente tutto

Poiché $è un carattere valido in regexps (end-of-line / buffer), probabilmente si desidera utilizzare le virgolette singole per contenere il regexp, a meno che non si stia memorizzando in una variabile. Se stai prendendo dati arbitrari da qualcuno non attendibile, dovrai sostituirlo 'con '"'"'e poi racchiudere tra virgolette singole.

Nota che [abc]_[x|y]sembra che tu voglia abbinare xo y, mentre in realtà corrisponde a uno dei tre personaggi xy|. Le parentesi quadre corrispondono ai caratteri all'interno e solo -per gli intervalli e ^a all'inizio per la negazione. Quindi, [abc]_(x|y)potrebbe essere quello che volevi dire, e le parentesi sono i personaggi che sono speciali per shell. Le parentesi quadre non sono speciali per shell, sembra proprio che lo siano. Le parentesi quadre [[ ... ]]sono speciali.


Questa è una delle risposte più corrette qui (io apprezzo soprattutto le istruzioni per la sostituzione 'con '"'"'), tuttavia, non è ancora corretta. [È un carattere speciale da shell, viene utilizzato nei caratteri jolly quando si esegue l'espansione del percorso (quale shell fa per tutto ciò che non è quotato).
jpalecek,

È speciale in alcuni contesti, come la sottoscrizione variabile o per il globbing, ma puoi ancora digitare foo=a[b]e quindi echo $fooe vedere che la stringa non ha bisogno di virgolette. Hai ragione, ero troppo breve.
Phil P

Se sei sfortunato, c'è un file abnella directory corrente e fooconterrà abinvece di a[b]. Cita le tue parentesi quadre, le persone.
Clacke,

(Per chiarezza: cito (come chiarito dalla risposta originale, dove stavo spingendo per un preventivo), e questo è un deragliamento laterale a cui mi sto rivolgendo). Questa affermazione mi ha sorpreso, quindi l'ho provato. Non è vero in zsh o bash, ma è vero in BSD / bin / sh. Questo è contro POSIX ed è un comportamento non standard, quindi dovrai citare per gestirlo. In zsh, puoi setopt glob_assignabilitare anche questo comportamento, quindi la citazione è la risposta più sicura.
Phil P,
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.