Załóżmy, że mam dane wyjściowe z polecenia (takiego jak ls -1
):
a
b
c
d
e
...
Chcę zastosować polecenie (powiedzmy echo
) do każdego z nich z kolei. Na przykład
echo a
echo b
echo c
echo d
echo e
...
Jak najłatwiej to zrobić w bash?
Załóżmy, że mam dane wyjściowe z polecenia (takiego jak ls -1
):
a
b
c
d
e
...
Chcę zastosować polecenie (powiedzmy echo
) do każdego z nich z kolei. Na przykład
echo a
echo b
echo c
echo d
echo e
...
Jak najłatwiej to zrobić w bash?
Odpowiedzi:
Jest to prawdopodobnie najłatwiejszy w użyciu xargs
. W Twoim przypadku:
ls -1 | xargs -L1 echo
-L
Flaga gwarantuje wejście jest prawidłowo odczytać. Ze strony podręcznika użytkownika xargs
:
-L number
Call utility for every number non-empty lines read.
A line ending with a space continues to the next non-empty line. [...]
ls
automatycznie robi to -1
w rurze.
ls | xargs -L2 echo
i ls -1 | xargs -L2 echo
daje dwa różne wyniki. Ten pierwszy jest na jednej linii.
xargs
może uruchamiać tylko pliki wykonywalne, a nie funkcje powłoki lub wbudowane polecenia powłoki. W przypadku tego pierwszego najlepszym rozwiązaniem jest prawdopodobnie rozwiązanie z read
pętlą.
-L1
.
Możesz użyć podstawowej operacji poprzedzającej w każdej linii:
ls -1 | while read line ; do echo $line ; done
Lub możesz przesłać dane wyjściowe do sed dla bardziej złożonych operacji:
ls -1 | sed 's/^\(.*\)$/echo \1/'
sh: cho: not found a sh: cho: not found
wygląda na to, że e
odbija się echem od polecenia sed lub czegoś takiego.
while
pętlę. cmd1 | while read line; do cmd2 $line; done
. Lub while read line; do cmd2 $line; done < <(cmd1)
który nie tworzy podpowłoki. To jest uproszczona wersja twojego sed
polecenia:sed 's/.*/echo &/'
"$line"
pętlę while, aby uniknąć podziału słów.
read -r line
aby uniknąć read
bałaganu ze znakami ucieczki. Na przykład echo '"a \"nested\" quote"' | while read line; do echo "$line"; done
daje "a "nested" quote"
, który stracił ucieczkę. Jeśli to zrobimy echo '"a \"nested\" quote"' | while read -r line; do echo "$line"; done
, otrzymamy "a \"nested\" quote"
zgodnie z oczekiwaniami. Zobacz wiki.bash-hackers.org/commands/builtin/read
Możesz użyć pętli for :
dla pliku w *; robić echo „$ file” Gotowe
Zauważ, że jeśli dane polecenie akceptuje wiele argumentów, wówczas użycie xargs jest prawie zawsze bardziej wydajne, ponieważ wystarczy tylko odrodzić dane narzędzie, a nie wiele razy.
printf '%s\0' * | xargs -0 ...
- w przeciwnym razie jest to dość niebezpieczne z nazwami plików z białymi spacjami, cytatami itp.
Rzeczywiście można używać sed to zrobić, pod warunkiem, że jest GNU sed.
... | sed 's/match/command \0/e'
Jak to działa:
cat /logs/lfa/Modified.trace.log.20150904.pw | sed -r 's/^(.*)(\|006\|00032\|)(.*)$/echo "\1\2\3 - ID `shuf -i 999-14999 -n 1`"/e'
for s in `cmd`; do echo $s; done
Jeśli cmd ma dużą moc wyjściową:
cmd | xargs -L1 echo
cmd
ma spacje na wyjściu, pierwsza nie powiedzie się.
xargs kończy się niepowodzeniem z odwrotnymi ukośnikami, cudzysłowami. To musi być coś podobnego
ls -1 |tr \\n \\0 |xargs -0 -iTHIS echo "THIS is a file."
Opcja xargs -0:
-0, --null Input items are terminated by a null character instead of by whitespace, and the quotes and backslash are not special (every character is taken literally). Disables the end of file string, which is treated like any other argument. Useful when input items might contain white space, quote marks, or backslashes. The GNU find -print0 option produces input suitable for this mode.
ls -1
kończy elementy znakami nowej linii, więc tr
tłumaczy je na znaki puste.
To podejście jest około 50 razy wolniejsze niż iteracja ręczna for ...
(patrz odpowiedź Michaela Aarona Safyana ) (3,55s vs. 0,066s). Ale w przypadku innych poleceń wejściowych, takich jak lokalizuj, znajdź, odczytuj z pliku ( tr \\n \\0 <file
) lub podobnego, musisz pracować w xargs
ten sposób.
Lepszy wynik dla mnie:
ls -1 | xargs -L1 -d "\n" CMD
find . -mindepth 1 -maxdepth 1 -print0 | xargs -0 command
zajmie się przypadkami, w których wynik ls -1
jest niejednoznaczny; używaj -printf '%P\0'
raczej, niż -print0
jeśli nie chcesz prowadzić ./
na każdym z nich.
ls -1
może być tutaj przykładem, ale ważne jest, aby pamiętać, że analizowanie wyniku nie jest dobrels
. Zobacz: mywiki.wooledge.org/ParsingLs