Припустимо, у мене є деякий вихід з команди (наприклад ls -1):
a
b
c
d
e
...
Я хочу застосувати команду (скажімо echo) до кожного, по черзі. Напр
echo a
echo b
echo c
echo d
echo e
...
Який найпростіший спосіб зробити це в баші?
Припустимо, у мене є деякий вихід з команди (наприклад ls -1):
a
b
c
d
e
...
Я хочу застосувати команду (скажімо echo) до кожного, по черзі. Напр
echo a
echo b
echo c
echo d
echo e
...
Який найпростіший спосіб зробити це в баші?
Відповіді:
Це, мабуть, найпростіше у використанні xargs. У вашому випадку:
ls -1 | xargs -L1 echo
-LПрапор забезпечує вхід правильно читати. З чоловічої сторінки 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автоматично виконує -1в трубі.
ls | xargs -L2 echoі ls -1 | xargs -L2 echoдай два різні виходи. Перші - всі на одній лінії.
xargsможе запускати лише виконувані файли, а не функції оболонки або вбудовані команди оболонки. Для першого найкращим рішенням є, мабуть, рішення з readциклом.
-L1, для чого.
Ви можете використовувати основні операції з поданням у кожному рядку:
ls -1 | while read line ; do echo $line ; done
Або ви можете передати висновок sed для більш складних операцій:
ls -1 | sed 's/^\(.*\)$/echo \1/'
sh: cho: not found a sh: cho: not foundсхоже, що це прийняття eecho - це команда sed чи щось таке.
whileциклу. cmd1 | while read line; do cmd2 $line; done. Або, while read line; do cmd2 $line; done < <(cmd1)що не створює підшару. Це спрощена версія вашої sedкоманди:sed 's/.*/echo &/'
"$line"цикл у той час, щоб уникнути розбиття слів.
read -r lineщоб запобігти readвозитися з втеченими символами. Наприклад echo '"a \"nested\" quote"' | while read line; do echo "$line"; doneдає "a "nested" quote", яка втратила свою втечу. Якщо ми це зробимо, echo '"a \"nested\" quote"' | while read -r line; do echo "$line"; doneми "a \"nested\" quote"очікували. Дивіться wiki.bash-hackers.org/commands/builtin/read
Ви можете використовувати цикл :
для файлу в *; робити відлуння "$ файл" зроблено
Зауважте, що якщо відповідна команда приймає декілька аргументів, то використання xargs майже завжди є більш ефективним, оскільки їй потрібно лише породжувати цю програму один раз, а не кілька разів.
printf '%s\0' * | xargs -0 ...- в іншому випадку, це досить небезпечно з назви файлів з пробілами, цитатами тощо
Ви дійсно можете використовувати sed для цього, якщо це GNU sed.
... | sed 's/match/command \0/e'
Як це працює:
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
Якщо cmd має великий вихід:
cmd | xargs -L1 echo
cmdу виході є пробіли, перший не вийде.
xargs не вдається зі зворотними нахилами, котируваннями. Це має бути щось на кшталт
ls -1 |tr \\n \\0 |xargs -0 -iTHIS echo "THIS is a file."
варіант 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закінчує елементи символами нового рядка, тому trпереводить їх у нульові символи.
Цей підхід приблизно в 50 разів повільніше, ніж повторення вручну for ...(див. Відповідь Майкла Аарона Сафяна ) (3,55s проти 0,066s). Але для інших команд введення, таких як пошук, пошук, читання з файлу ( tr \\n \\0 <file) або подібного, вам доведеться працювати з xargsподібним чином.
Кращий результат для мене:
ls -1 | xargs -L1 -d "\n" CMD
find . -mindepth 1 -maxdepth 1 -print0 | xargs -0 commandбуде обробляти випадки, коли вихід ls -1неоднозначний; використовувати, -printf '%P\0'а не -print0якщо ви не хочете ведучого ./на кожному.
ls -1Можливо, це може бути прикладом, але важливо пам’ятати, що не добре розбирати результатls. Дивіться: mywiki.wooledge.org/ParsingLs