Vraag Wat is het verschil tussen dubbele en enkele vierkante haakjes in bash?


Ik vroeg me af wat precies het verschil was tussen

[[ $STRING != foo ]]

en

[ $STRING != foo ]

is, behalve dat de laatste posix-compliant is, gevonden in sh en de eerste is een extensie gevonden in bash.


344
2017-08-09 21:11


oorsprong


stackoverflow.com/questions/13542832 - Ciro Santilli 新疆改造中心 六四事件 法轮功
In het geval dat je je ook afvroeg of je helemaal geen haakjes gebruikte, bijvoorbeeld in de context van een if verklaring, zie mywiki.wooledge.org/BashPitfalls#if_.5Bgrep_foo_myfile.5D - Kev
ook uit de documenten van Ubuntu: wiki.ubuntu.com/... - radistao


antwoorden:


Er zijn verschillende verschillen. Naar mijn mening zijn enkele van de belangrijkste:

  1. [ is een ingebouwde Bash en vele andere moderne shells. De ingebouwde [ is gelijkaardig aan test met de extra eis van een sluiting ]. De ingebouwde [ en test imiteren van de functionaliteit /bin/[ en /bin/test samen met hun beperkingen, zodat scripts achterwaarts compatibel zouden zijn. De oorspronkelijke uitvoerbare bestanden bestaan ​​nog steeds voornamelijk voor naleving van POSIX en compatibiliteit met eerdere versies. De opdracht uitvoeren type [ in Bash geeft dat aan [ wordt standaard geïnterpreteerd als een ingebouwde. (Notitie: which [ zoekt alleen naar uitvoerbare bestanden op de PAD en is equivalent aan type -p [)
  2. [[ is niet zo compatibel, het zal niet noodzakelijk met wat dan ook werken /bin/sh wijst naar. Zo [[ is de modernere Bash / Zsh / Ksh-optie.
  3. Omdat [[ is ingebouwd in de shell en heeft geen legacy-vereisten, u hoeft zich geen zorgen te maken over het splitsen van woorden op basis van de IFS variabele om te verknoeien aan variabelen die evalueren naar een string met spaties. Daarom hoef je de variabele niet echt in dubbele aanhalingstekens te zetten.

Voor het grootste deel is de rest slechts een wat leukere syntaxis. Om meer verschillen te zien, raad ik deze link aan bij een FAQ-antwoord: Wat is het verschil tussen test, [en [[?. In feite, als je serieus bent over bash scripting, raad ik aan om het volledige te lezen wiki, inclusief de veelgestelde vragen, valkuilenen gids. De testsectie uit de gidssectie verklaart ook deze verschillen, en waarom de auteur (s) denken [[ is een betere keuze als u zich geen zorgen hoeft te maken over het draaggemak. De belangrijkste redenen zijn:

  1. U hoeft zich geen zorgen te maken over het citeren van de linkerkant van de test, zodat deze daadwerkelijk wordt gelezen als een variabele.
  2. Je hoeft niet te ontkomen aan minder dan en groter dan < > met backslashes zodat ze niet worden geëvalueerd als invoeromleiding, wat sommige dingen echt kan verpesten door het overschrijven van bestanden. Dit gaat weer terug naar [[ een ingebouwde zijn. Als [(test) een extern programma is, zou de shell een uitzondering moeten maken op de manier waarop het evalueert < en > alleen als /bin/test wordt gebeld, wat niet echt logisch zou zijn.

261
2017-08-09 21:56



Bedankt, de link naar de bash FAQ was waar ik naar op zoek was (wist niet van die pagina, bedankt). - 0x89
Ik heb je bericht bewerkt met deze informatie, maar [en test worden uitgevoerd als ingebouwde items. De builtins zijn ontworpen om / bin / [en / bin / test te vervangen, maar moesten ook de beperkingen van de binaries reproduceren. Het commando 'type [' verifieert dat de ingebouwde wordt gebruikt. 'welke [' alleen zoekt naar uitvoerbare bestanden in het PATH en gelijk is aan 'type -P [' - klynch


Kortom:

[is een bash ingebouwde

[[]] zijn bash trefwoorden

sleutelwoorden: Zoekwoorden lijken heel veel op builtins, maar het belangrijkste verschil is dat er speciale parseerregels op van toepassing zijn. [Is bijvoorbeeld een bash ingebouwd, terwijl [[een bash-sleutelwoord is. Ze worden allebei gebruikt om dingen te testen, maar omdat [[een trefwoord is in plaats van een ingebouwde, profiteert het van een paar speciale parseerregels die het een stuk eenvoudiger maken:

  $ [ a < b ]
 -bash: b: No such file or directory
  $ [[ a < b ]]

Het eerste voorbeeld retourneert een fout omdat bash probeert het bestand b om te leiden naar het commando [a]. Het tweede voorbeeld doet eigenlijk wat u ervan verwacht. Het karakter <heeft niet langer de speciale betekenis van Bestandsomleiding-operator.

Bron: http://mywiki.wooledge.org/BashGuide/CommandsAndArguments


108
2017-12-29 19:42



[ is een POSIX shell-opdracht; het hoeft niet ingebouwd te worden. ] is slechts een argument waarnaar dat commando zoekt, zodat de syntaxis in evenwicht is. Het commando is een synoniem voor test behalve dat test zoekt geen sluiting ]. - Kaz
Kijk hier: pubs.opengroup.org/onlinepubs/009695399/utilities/test.html - Kaz


Gedragsverschillen

Getest in Bash 4.3.11:

  • POSIX versus Bash-extensie:

  • normale opdracht versus magie

    • [ is gewoon een normale opdracht met een rare naam.

      ] is slechts een argument van [ dat voorkomt dat er meer argumenten worden gebruikt.

      Ubuntu 16.04 heeft daar eigenlijk een uitvoerbaar bestand voor /usr/bin/[ geleverd door coreutils, maar de bash-ingebouwde versie heeft voorrang.

      Er is niets veranderd aan de manier waarop Bash het commando parseert.

      Met name, < is omleiding, && en || meerdere opdrachten samenvoegen, ( ) genereert subschalen, tenzij er aan ontsnapt zijn \en woorduitbreiding gebeurt zoals gewoonlijk.

    • [[ X ]] is een enkele constructie die maakt X magisch worden ontleed. <, &&, || en () worden speciaal behandeld en regels voor het splitsen van woorden zijn anders.

      Er zijn ook nog meer verschillen zoals = en =~.

    In Bashese: [ is een ingebouwd commando, en [[ is een sleutelwoord: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword

  • <

  • && en ||

    • [[ a = a && b = b ]]: waar, logisch en
    • [ a = a && b = b ]: syntax error, && geparseerd als een AND-opdrachtscheidingsteken cmd1 && cmd2 
    • [ a = a -a b = b ]: equivalent, maar verouderd door POSIX
    • [ a = a ] && [ b = b ]: POSIX-aanbeveling
  • (

    • [[ (a = a || a = b) && a = b ]]: false
    • [ ( a = a ) ]: syntax error, () wordt geïnterpreteerd als een subshell
    • [ \( a = a -o a = b \) -a a = b ]: equivalent, maar () wordt vervangen door POSIX
    • ([ a = a ] || [ a = b ]) && [ a = b ] POSIX-aanbeveling
  • woordsplitsing

    • x='a b'; [[ $x = 'a b' ]]: waar, citaten niet nodig
    • x='a b'; [ $x = 'a b' ]: syntaxisfout, wordt uitgebreid naar [ a b = 'a b' ]
    • x='a b'; [ "$x" = 'a b' ]: gelijkwaardig
  • =

    • [[ ab = a? ]]: waar, omdat dat zo is patroonovereenkomst (* ? [ zijn magisch). Breidt niet uit naar bestanden in de huidige map.
    • [ ab = a? ]: a? glob breidt uit. Het kan dus waar of onwaar zijn, afhankelijk van de bestanden in de huidige map.
    • [ ab = a\? ]: false, niet glob expansie
    • = en == zijn in beide hetzelfde [ en [[, maar == is een Bash-extensie.
    • printf 'ab' | grep -Eq 'a.': POSIX ERE-equivalent
    • [[ ab =~ 'ab?' ]]: false, verliest magie met ''
    • [[ ab? =~ 'ab?' ]]: waar
  • =~

    • [[ ab =~ ab? ]]: waar, POSIX uitgebreide reguliere expressie wedstrijd, ? breidt niet uit
    • [ a =~ a ]: syntax error
    • printf 'ab' | grep -Eq 'ab?': POSIX-equivalent

Aanbeveling

Ik geef er de voorkeur aan om altijd te gebruiken [].

Er zijn POSIX-equivalenten voor elke [[ ]] ik heb het gezien.

Als je gebruikt [[ ]] u:

  • draagbaarheid verliezen
  • dwing de lezer om de fijne kneepjes van een andere bash-extensie te leren. [is gewoon een normale opdracht met een rare naam, er is geen speciale semantiek bij betrokken.

61
2017-07-12 10:22



Hoe te gebruiken printf 'ab' | grep -Eq 'ab?' binnen if [ … ]? - meeDamian
@meeDamian if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi. [] is een commando net als grep. De () mogelijk niet nodig op dat commando, ik weet het niet zeker: ik heb het toegevoegd vanwege de |, hangt af van hoe Bash dingen parseert. Als er geen was | Ik weet zeker dat je gewoon kunt schrijven if cmd arg arg; then. - Ciro Santilli 新疆改造中心 六四事件 法轮功
@meeDamian ja, geen behoefte aan () het lijkt: stackoverflow.com/questions/8965509/... - Ciro Santilli 新疆改造中心 六四事件 法轮功
Mooie lijst! Zie ook: wiki.ubuntu.com/... - radistao


Gebaseerd op een snelle lezing van de relevante delen van de manpage, lijkt het primaire verschil te zijn dat de == en != operators komen overeen met een patroon in plaats van een letterlijke tekenreeks, en ook dat er de =~ regex-vergelijkingsoperator.


4
2017-08-09 21:17





Enkele beugel d.w.z. [] is geschikt voor een POSIX-shell om een ​​voorwaardelijke uitdrukking in te sluiten.

Dubbele haakjes d.w.z. [[]] is een verbeterde (of verlengde) versie van de standaard POSIX-versie, dit wordt ondersteund door bash en andere shells (zsh, ksh).

In bash gebruiken we voor numerieke vergelijking eq, ne,lt en gt, met dubbele haakjes ter vergelijking die we kunnen gebruiken ==, !=, <, en > letterlijk.

  • [ is een synoniem voor testopdracht. Zelfs als het is ingebouwd in de shell, creëert het een nieuw proces.
  • [[ is een nieuwe, verbeterde versie ervan, een sleutelwoord en geen programma.

bijvoorbeeld:

[ var1 lt var2] #works
[ var1 < var2] #error: var2 No such file or directory 
[ var1 \< var2] #works with escape
[[ var1 < var2]] #works

3
2018-02-08 03:15