Mam dość prosty skrypt, który jest podobny do następującego:
#!/bin/bash
VAR1="$1"
MOREF='sudo run command against $VAR1 | grep name | cut -c7-'
echo $MOREF
Kiedy uruchamiam ten skrypt z wiersza poleceń i przekazuję mu argumenty, nie otrzymuję żadnych danych wyjściowych. Jednak po uruchomieniu poleceń zawartych w $MOREF
zmiennej jestem w stanie uzyskać dane wyjściowe.
Jak wziąć wyniki polecenia, które należy uruchomić w skrypcie, zapisać je w zmiennej, a następnie wypisać na ekranie?
bash
shell
command-line
Jan
źródło
źródło
echo
zmienna jest bezużyteczny wykorzystanieecho
, a bezużyteczny stosowanie zmiennych.Odpowiedzi:
Oprócz backticksów
`command`
, podstawianie poleceń można wykonać za pomocą$(command)
lub"$(command)"
, co uważam za łatwiejsze do odczytania i pozwala na zagnieżdżanie.Quoting (
"
) ma znaczenie dla zachowania wartości zmiennych wieloliniowych ; jest to opcjonalne po prawej stronie zadania, ponieważ dzielenie słów nie jest wykonywane , więcOUTPUT=$(ls -1)
działałoby dobrze.źródło
echo
polecenia.${OUTPUT}foo
. Są one również wymagane podczas wykonywania wbudowanych operacji na łańcuchach zmiennej, takich jak${OUTPUT/foo/bar}
Właściwa droga to
Jeśli masz zamiar użyć apostrofu, trzeba
`
, nie'
. Ta postać nazywa się „backticks” (lub „grave accent”).Lubię to:
źródło
echo
.$()
pracy. Nie udało się naprawić, dopóki nie zobaczyłem tej strony.Niektóre triki Bash, których używam do ustawiania zmiennych z poleceń
2. edycja 2018-02-12: Dodano inny sposób, wyszukaj na dole tego zadania długoterminowe !
2018-01-25 Edytuj: dodano przykładową funkcję (do zapełniania zmiennych dotyczących użycia dysku)
Pierwszy prosty, stary i zgodny sposób
W większości kompatybilny, drugi sposób
Ponieważ zagnieżdżanie może stać się ciężkie, zastosowano w tym celu nawiasy
Próbka zagnieżdżona:
Odczytywanie więcej niż jednej zmiennej (z Bashisms )
Jeśli chcę tylko użyć wartości:
możesz zobaczyć zmienną tablicową :
Następnie:
Ale wolę to:
Pierwszy z
read foo
nich po prostu pominie wiersz nagłówka, ale tylko w jednym poleceniu zapełnisz 7 różnych zmiennych:Lub nawet:
... będzie działać również z tablicami asocjacyjnymi :
read foo disk[total] disk[used] ...
Przykładowa funkcja do zapełniania niektórych zmiennych:
Uwaga:
declare
linia nie jest wymagana, tylko ze względu na czytelność.O
sudo cmd | grep ... | cut ...
(Unikaj bezużytecznego
cat
! Więc to tylko jeden widelec mniej:Wszystkie potoki (
|
) oznaczają widelce. Gdzie trzeba uruchomić inny proces, dostęp do dysku, wywołania bibliotek i tak dalej.Zatem użycie
sed
próbki, ograniczy podproces do tylko jednego rozwidlenia :I z Bashismami :
Ale w przypadku wielu działań, głównie na małych plikach, Bash mógł wykonać to samo:
lub
Idąc dalej na temat dzielenia zmiennych ...
Spójrz na moją odpowiedź na temat Jak podzielić ciąg na ograniczniku w Bash?
Alternatywa: zmniejszenie liczby widelców przy użyciu długoterminowych zadań w tle
2. edycja 2018-02-12:
Aby zapobiec wielu rozwidleniom, takim jak
lub
Działa to dobrze, ale uruchamianie wielu widelców jest ciężkie i wolne.
Polecenia takie jak
date
ibc
mogą wykonywać wiele operacji, linia po linii !!Widzieć:
Możemy więc użyć długiego procesu w tle, aby wykonać wiele zadań, bez konieczności inicjowania nowego rozwidlenia dla każdego żądania.
Potrzebujemy tylko kilku deskryptorów plików i fifos, aby zrobić to poprawnie:
(Oczywiście, FD
5
i6
muszą być nieużywane!) ... Stamtąd możesz skorzystać z tego procesu poprzez:W funkcję
newConnector
Możesz znaleźć moją
newConnector
funkcję na GitHub.Com lub na mojej własnej stronie (uwaga na GitHub: w mojej witrynie są dwa pliki. Funkcja i wersja demo są umieszczone w jednym pliku, który można wykorzystać lub uruchomić w celu pokazu).Próba:
Funkcja
myBc
umożliwia użycie zadania w tle z prostą składnią i dla daty:Stamtąd, jeśli chcesz zakończyć jeden z procesów w tle, wystarczy zamknąć jego fd :
co nie jest potrzebne, ponieważ wszystkie fd zamykają się po zakończeniu głównego procesu.
źródło
EXISTING_CONTAINER=$(docker ps -a | grep "$(echo $CONTAINER_NAME)")
to stwierdzenie, którego szukałem.echo
; chcesz po prostugrep "$CONTAINER_NAME"
tput
jako zadanie tła do renderowania kolorów na terminalu !!kubectl get ns | while read -r line; do echo
$ line | grep Termin | cut -d '-f1; done
wypisuje dla każdej$line
pustej linii, a następniebash: xxxx: command not found
. Spodziewam się jednak, że zostanie wydrukowanyxxx
Jak już ci wskazali, powinieneś użyć „backticks”.
Proponowana alternatywa również
$(command)
działa i jest łatwiejsza do odczytania, ale należy pamiętać, że jest ważna tylko z Bash lub KornShell (i powłokami z nich pochodnymi), więc jeśli twoje skrypty muszą być naprawdę przenośne na różnych systemach uniksowych, powinieneś preferować stara notacja wsteczna.źródło
$()
jest w pełni kompatybilny z POSIX sh, znormalizowanym ponad dwie dekady temu./bin/sh
w systemie Solaris 10 nadal nie rozpoznaje$(…)
- i AFAIK to prawda również w systemie Solaris 11./bin/sh
jestksh93
.$()
w powłoce POSIX na HP-UX od ponad 10 lat.Znam trzy sposoby, aby to zrobić:
Funkcje są odpowiednie do takich zadań: **
Przywołaj to, mówiąc
func
.Ewentualne może być także inne odpowiednie rozwiązanie:
Trzeci używa bezpośrednio zmiennych:
Możesz uzyskać wynik trzeciego rozwiązania w dobry sposób:
A także w paskudny sposób:
źródło
"$var"
dobry i$var
paskudny?Żeby być innym:
źródło
Ustawiając zmienną, upewnij się, że NIE masz spacji przed i / lub po znaku = . Dosłownie spędziłem godzinę próbując to rozgryźć, próbując wszelkiego rodzaju rozwiązań! To nie jest fajne.
Poprawny:
Zakończy się niepowodzeniem z błędem „rzeczy: not found” lub podobny
źródło
var=value somecommand
przejazdysomecommand
zvar
w środowisku o wartościvalue
. Tak więcvar= somecommand
eksportujevar
w środowiskusomecommand
z pustą wartością (zero-bajtową).Jeśli chcesz to zrobić za pomocą polecenia multiline / multiple / s, możesz to zrobić:
Lub:
Przykład:
Wynik:
Korzystając z heredoc , możesz bardzo łatwo uprościć sprawę , dzieląc swój długi, jednoliniowy kod na wielowierszowy. Inny przykład:
źródło
bash
w podstawieniu polecenia? Już tworzysz podpowłokę przez samo podstawienie polecenia. Jeśli chcesz wstawić wiele poleceń, po prostu oddziel je znakiem nowej linii lub średnikiem.output=$(echo first; echo second; ...)
'bash -c "bash -c \"bash -c ...\""'
byłoby też „inaczej”; ale nie widzę sensu tego.ssh
sudo -s
wykonywanie poleceń mysql wewnątrz itp. (Zamiast bash)variable=$(bash -c 'echo "foo"; echo "bar"')
ponadvariable=$(echo "foo"; echo "bar")
- tu dokument jest po prostu mechanizm cytowanie i naprawdę nie dodaje niczego oprócz innego bezużyteczne komplikacji.ssh -p $port $user@$domain /bin/bash <<EOF
, aby zapobiecPseudo-terminal will not be allocated because stdin is not a terminal.
ostrzeżeniuMusisz użyć albo
$(command-here)
lub
Przykład
źródło
$()
jest znacznie lepszy niż backticks. Zobacz: Jaka jest korzyść z używania $ () zamiast backticksa w skryptach powłoki?Jest to inny sposób i dobrze jest go używać z niektórymi edytorami tekstu, które nie są w stanie poprawnie wyróżnić każdego skomplikowanego kodu, który tworzysz:
źródło
Możesz użyć tyknięć (znanych również jako groby akcentowe) lub
$()
.Lubić:
Oba mają ten sam efekt. Ale WYJŚCIE = $ (x + 2) jest bardziej czytelne i najnowsze.
źródło
Jeśli polecenie, które próbujesz wykonać, nie powiedzie się, zapisuje dane wyjściowe w strumieniu błędów, a następnie zostanie wydrukowane w konsoli.
Aby tego uniknąć, musisz przekierować strumień błędów:
źródło
Niektórzy mogą uznać to za przydatne. Wartości całkowite w podstawianiu zmiennych, gdzie lewica używa
$(())
podwójnych nawiasów:źródło
for ((...))
pętla wydawałaby się lepszym dopasowaniem do zmiennej pętli ). Nie powinieneś także używać wielkich liter w swoich zmiennych prywatnych.ARR=(3 2 4 1);for((N=3,M=3,COUNT=N-1;COUNT < ${#ARR[@]};ARR[COUNT]*=M,COUNT+=N)){ :;}
ale zgadzam się z @tripleee: Nie rozumiem, co to robi!Oto dwa kolejne sposoby:
Pamiętaj, że w Bash przestrzeń jest bardzo ważna. Tak więc, jeśli chcesz, aby twoje polecenie działało, używaj bez zmian, bez wprowadzania spacji.
Poniższy przypisuje
harshil
doL
, a następnie wydrukowanie goPoniżej przypisuje dane wyjściowe polecenia
tr
do L2.tr
jest obsługiwany na innej zmiennej, L1.źródło
$"..."
prawdopodobnie nie robi tego, co myślisz, że robi . 2. Jest to już podane w odpowiedzi Andy'ego Lestera.echo ${L1,,}
do zmniejszenia lubecho ${L1^^}
zwiększenia.