2010-07-14 12:51:58 +0000 2010-07-14 12:51:58 +0000
32
32

bash: hoe commandoregelargumenten doorgeven die speciale tekens bevatten

Ik heb voor mezelf een linux-programma program geschreven dat een reguliere expressie als invoer nodig heeft.

Ik wil het programma aanroepen in de bash commandoregel en die reguliere expressie als een commandoregelargument aan het programma doorgeven (er zijn ook andere commandoregelargumenten). Een typische reguliere expressie ziet eruit als

[abc]\_[x|y]

Helaas zijn de karakters [, ], en | speciale karakters in bash. Dus,

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

aanroepen werkt niet. Is er een manier om de expressie door te geven door een soort escape tekens of aanhalingstekens enz. te gebruiken?

(Het aanroepen van program "[abc]\_[x|y] anotheragument" werkt ook niet, omdat het de twee argumenten als één interpreteert).

Antwoorden (8)

29
29
29
2010-07-14 12:59:46 +0000

Je kunt

  1. Elk speciaal symbool escapen met een backslash (zoals in \[abc\]_\[x\|y\]) of
  2. 2. Het hele argument dubbel aanhalen (zoals in "[abc]_[x|y]").

EDIT: Zoals sommigen hebben opgemerkt, verhindert dubbele aanhalingstekens variabele uitbreiding of opdrachtsubstitutie niet. Daarom, als je regex iets bevat dat door bash geïnterpreteerd kan worden als een van deze, gebruik dan enkele aanhalingstekens in plaats daarvan.

28
28
28
2011-10-21 12:19:50 +0000

Gebruik enkele aanhalingstekens. Enkele aanhalingstekens zorgen ervoor dat geen van de tekens wordt geïnterpreteerd.

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

Er zijn twee oplossingen als je een enkel aanhalingsteken moet insluiten:

$ 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!]
6
6
6
2010-07-15 06:09:18 +0000

Per man bash

Er zijn drie aanhalingstekens: het escape teken, enkele aanhalingstekens, en dubbele aanhalingstekens.

Een backslash zonder aanhalingstekens ( **** ) is het escape-teken. Het behoudt de letterlijke waarde van het volgende teken dat volgt, met uitzondering van <newline>. Als een ** ** <newline> paar verschijnt, en de backslash is zelf niet geciteerd, dan wordt de ** ** <newline> behandeld als een regelvoortzetting (dat wil zeggen, het wordt verwijderd uit de invoerstroom en effectief genegeerd).

Als u tekens tussen enkele aanhalingstekens zet, blijft de letterlijke waarde van elk teken binnen de aanhalingstekens behouden. Een enkel aanhalingsteken mag niet tussen enkele aanhalingstekens staan, zelfs niet als het wordt voorafgegaan door een backslash.

Tekens tussen dubbele aanhalingstekens behouden de letterlijke waarde van alle tekens binnen de aanhalingstekens, met uitzondering van $ , ` , ** , and, when history expansion is enabled, **!. The characters $ and ` behouden hun speciale betekenis binnen dubbele aanhalingstekens. De backslash behoudt zijn speciale betekenis alleen wanneer deze wordt gevolgd door een van de volgende tekens: $ , ` , , **** , of . Een dubbel aanhalingsteken kan binnen dubbele aanhalingstekens worden aangehaald door het vooraf te laten gaan door een backslash. Indien ingeschakeld, zal de geschiedenis worden uitgebreid tenzij een ! tussen dubbele aanhalingstekens wordt ge-escaped met een backslash. De backslash die aan de ! voorafgaat, wordt niet verwijderd.

De speciale parameters ***** en @ hebben een speciale betekenis wanneer ze tussen dubbele aanhalingstekens staan (zie PARAMETERS hieronder).

Woorden van de vorm $‘ string worden speciaal behandeld. Het woord wordt uitgebreid tot string, waarbij backslash-geëscaped tekens worden vervangen zoals gespecificeerd door de ANSI C standaard. Backslash escape sequenties, indien aanwezig, worden als volgt gedecodeerd:

**\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**  

Het uitgebreide resultaat is enkel aanhalingstekens, alsof het dollarteken niet aanwezig was. 

Een tekenreeks met dubbele aanhalingstekens, voorafgegaan door een dollarteken ( **$"** _string_ **"** ), zorgt ervoor dat de tekenreeks wordt vertaald volgens de huidige locale. Als de huidige locale **C** of **POSIX** is, wordt het dollarteken genegeerd. Als de tekenreeks wordt vertaald en vervangen, wordt de vervanging dubbel geciteerd. **single quote** \" **double quote** \**_nnn_ the eight-bit character whose value is the octal value _nnn_ (one to three digits)**\x**_HH_ the eight-bit character whose value is the hexadecimal value _HH_ (one or two hex digits)**\u**_HHHH_ the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value _HHHH_ (one to four hex digits)**\U**_HHHHHHHH_ the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value _HHHHHHHH_ (one to eight hex digits)**\c**_x_ a control-_x_ character

Het uitgebreide resultaat is enkel aanhalingstekens, alsof het dollarteken niet aanwezig was.

Een tekenreeks met dubbele aanhalingstekens, voorafgegaan door een dollarteken ( $” string ), zorgt ervoor dat de tekenreeks wordt vertaald volgens de huidige locale. Als de huidige locale C of POSIX is, wordt het dollarteken genegeerd. Als de tekenreeks wordt vertaald en vervangen, wordt de vervanging dubbel geciteerd.

2
2
2
2010-07-15 02:11:13 +0000

Hoewel het misschien niet nuttig is als regex, kunnen sommige tekenreeksen worden geïnterpreteerd als Bash variabele namen. Om dit te voorkomen en te voorkomen dat ze worden uitgebreid, gebruikt u enkele aanhalingstekens in plaats van dubbele aanhalingstekens:

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

Citeer elk argument afzonderlijk (als ze moeten worden gequote) zodat ze als onafhankelijke argumenten worden geïnterpreteerd. Je kunt in sommige gevallen ook arrays gebruiken:

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
2
2
2
2010-07-14 12:57:29 +0000

U kunt een backslash ( `U kunt een backslash ( ) gebruiken voor speciale tekens om ze te escapen, zoals hieronder:

john@awesome:~ # echo 0x1& &
1
1
1
2010-07-14 12:56:05 +0000
program "[abc]_[x|y]"
program "[abc]_[x|y]" anotherargument
0
0
0
2010-07-15 07:18:57 +0000

Waar komt het patroon vandaan? Is het vast of van een gebruiker? Is het de gebruiker die het script aanroept op het lokale systeem, of iemand op afstand?

Je gebruikt aanhalingstekens om gegevens in te pakken zodat de shell ze niet interpreteert. Er zijn twee mogelijkheden:

  1. Dubbele aanhalingstekens, die nog enige interpretatie toestaan ($expand en backticks)
  2. Dubbele aanhalingstekens, die alles doorlaten.

Omdat $ een geldig karakter is in regexps (einde-van-de-regel/buffer) wil je waarschijnlijk single-quotes gebruiken om de regexp vast te houden, tenzij je hem in een variabele opslaat. Als je willekeurige data van een onbetrouwbaar iemand neemt, moet je ' vervangen door '"'"' en dan wikkelen in enkele aanhalingstekens.

Merk op dat [abc]_[x|y] eruit ziet alsof je wilt overeenkomen met x of y, terwijl het eigenlijk overeenkomt met een van de drie karakters xy|. De vierkante haakjes komen overeen met de tekens binnen en alleen met - voor bereiken en een ^ aan het begin voor ontkenning. Dus, [abc]_(x|y) zou kunnen zijn wat je bedoelde, en de haakjes zijn de karakters die speciaal zijn voor shell. Vierkante haakjes zijn niet speciaal voor shell, het lijkt alleen alsof ze dat zijn. Dubbele-vierkante haakjes [[...]] zijn speciaal.

0
0
0
2010-07-14 12:57:13 +0000

Ze escapen zou goed moeten werken:

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