Jak prawidłowo zagnieżdżać backticks Bash


95

Albo brakowało mi jakiegoś luzu, albo luzowanie nie wydaje się działać przy zbyt dużej zapętleniu cytowań programisty.

$ echo "hello1-`echo hello2-\`echo hello3-\`echo hello4\`\``"

hello1-hello2-hello3-echo hello4

Chciał

hello1-hello2-hello3-hello4-hello5-hello6-...

Pytanie powinno prawdopodobnie brzmieć „Jak rekurencyjnie używać znaków odwrotnych Bash”. To powinno pomóc Googlersom.
Joey Adams

co to jest, co próbujesz zrobić.? to nie ma żadnego znaczenia.
ghostdog74

1
@joey, zmiana tytułu, witamy: D
Stormenet

1
Ups, zerwij to. Powinien brzmieć „Jak zagnieżdżać backticks w bash?” . Pomieszałem rekursję i zagnieżdżanie.
Joey Adams

deprecatedDlatego należy używać backticks $(cmd).
Timo,

Odpowiedzi:


149

Użyj $(commands)zamiast tego:

$ echo "hello1-$(echo hello2-$(echo hello3-$(echo hello4)))"
hello1-hello2-hello3-hello4

$(commands) robi to samo, co grawerunki, ale możesz je zagnieżdżać.

Możesz być także zainteresowany rozszerzeniami serii Bash:

echo hello{1..10}
hello1 hello2 hello3 hello4 hello5 hello6 hello7 hello8 hello9 hello10

+1, jak {1..10}. Ograniczyć to za pomocą tablicy? ZSH może „$ {$ (data) [2,4]}”. Dlaczego nie: "echo $ {echo hello1 - $ (echo hello2) [1]}"?
hhh

35

jeśli nalegasz na używanie odwrotnych apostrofów, możesz wykonać następujące czynności

$ echo "hello1-`echo hello2-\`echo hello3-\\\`echo hello4\\\`\``"

musisz wstawić odwrotne ukośniki, \\ \\\\ \\\\\\\\przez 2x i tak dalej, jest to po prostu bardzo brzydkie, użyj $(commands)jak inne sugerowane.


11

Za każdym razem, gdy chcesz ocenić polecenie, użyj command substitution:

$(command)

Za każdym razem, gdy chcesz ocenić wyrażenie arytmetyczne, użyj expression substitution:

$((expr))

Możesz zagnieżdżać te w ten sposób:

Powiedzmy, że plik1.txt ma 30 linii, a plik2.txt 10 linii, niż możesz ocenić takie wyrażenie:

$(( $(wc -l file1.txt) - $(wc -l file2.txt) ))

co zwróci 20 (różnica w liczbie wierszy między dwoma plikami).


10

Jest o wiele łatwiej, jeśli używasz $(cmd) składni podstawiania poleceń basha , która jest znacznie bardziej przyjazna dla zagnieżdżania:

$ echo "hello1-$(echo hello2-$(echo hello3-$(echo hello4)))"
hello1-hello2-hello3-hello4

5
Nie jest to ograniczone do bash . Jest dostępny we wszystkich powłokach zgodnych z POSIX 1003.1 („powłoki POSIX”) i większości powłok pochodzących od Bourne'a ( ksh , ash , dash , bash , zsh , itp.), Ale nie w rzeczywistej powłoce Bourne'a (tj. Heirloom.sourceforge.net /sh.html ).
Chris Johnsen,

wow, sygnatura czasowa tej odpowiedzi jest IDENTYCZNA jak ta w odpowiedzi @joey_adams! Synchronizacja w swoim najbardziej dosłownym znaczeniu :) Głosowanie również tutaj (:
drevicko

0

Czasami zagnieżdżanie odwrotne można zastąpić xargsrurami i

$ echo hello4 | xargs echo hello3 | xargs echo hello2 | xargs echo hello1
hello1 hello2 hello3 hello4

Wadą tego rozwiązania są:

  • Wszystkie argumenty należy podać w odwrotnej kolejności (4 → 1);
  • Wszystkie argumenty zostaną oddzielone spacjami (możliwe do rozwiązania za pomocą tr):

    $ echo hello4 | xargs echo hello3 | xargs echo hello2 | xargs echo hello1 | tr ' ' '-'
    hello1-hello2-hello3-hello4
    


Pokażmy prawdziwy przypadek użycia.

Następujące polecenia działają w bash, ale nie w tcsh (zagnieżdżanie lewych apostrofów nie jest obsługiwane zbyt dobrze w tcsh)

$ ls $(dirname $(which bash))
$ ls `dirname \`which bash\``

Można je zastąpić

$ which bash | xargs dirname | xargs ls
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.