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-...
hhh
źródło
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
Joey Adams
źródło
+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.

TY
źródło
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).

toobsco42
źródło
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
Mark Rushakoff
źródło
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
GC
źródło