2010-04-26 3 views
119

Предположим, у меня есть некоторый вывод команды (например, ls -1):Как применить команду оболочки к каждой строке вывода команды?

a 
b 
c 
d 
e 
... 

Я хочу, чтобы применить команду (например echo) для каждого из них, в свою очередь. Например.

echo a 
echo b 
echo c 
echo d 
echo e 
... 

Самый простой способ сделать это в bash?

ответ

139

Это, вероятно, самый простой в использовании xargs. В вашем случае:

ls -1 | xargs -L1 echo 
+15

'ls' автоматически выполняет' -1' в трубе. –

+5

@Dennis, не выглядит так: 'ls | xargs -L2 echo' и 'ls -1 | xargs -L2 echo' дают два разных выхода. Первый был на одной линии. –

+1

@Alex: Я получаю тот же результат. –

8

Вы можете использовать for loop:

 
for file in * ; do 
    echo "$file" 
done 

Обратите внимание, что если команда в вопросе принимает несколько аргументов, то с помощью xargs почти всегда более эффективна, поскольку оно имеет только нереститься утилиту в вопросе один раз вместо нескольких раз.

+1

Стоит описать правильное/безопасное использование xargs, т.е. 'printf '% s \ 0' * | xargs -0 ... '- в противном случае это довольно опасно с именами файлов с пробелами, кавычками и т. д. –

98

Вы можете использовать основные операции добавьте в начале каждой строки:

ls -1 | while read line ; do echo $line ; done 

Или вы можете перенаправить вывод в СЭД для более сложных операций:

ls -1 | sed 's/^\(.*\)$/echo \1/' 
+0

Команда sed не работает:' sh: cho: не найдено sh: cho: not found' Looks подобно тому, как «e» в эхо является командой sed или чем-то еще. –

+0

+1 для цикла while. 'cmd1 | при чтении строки; do cmd2 $ line; done'. Или 'while read line; do cmd2 $ line; done <<(cmd1) ", который не создает подоболочку. Это упрощенная версия вашей команды 'sed':' sed 's /.*/ echo & /' ' –

+1

@Alex: сменить двойные кавычки на одинарные кавычки. –

2
for s in `cmd`; do echo $s; done 

Если CMD имеет большой выход:

cmd | xargs -L1 echo 
+6

, если 'cmd' имеет пробелы в своем выходе, первый будет терпеть неудачу. –

+0

http://mywiki.wooledge.org/DontReadLinesWithFor, http://mywiki.wooledge.org/BashPitfalls entry # 1 –

6

Вы на самом деле может использовать SED, чтобы сделать это, при условии, что это GNU СЭД.

... | sed 's/match/command \0/e' 

Как это работает:

  1. Заменителя матч с командой матчем
  2. О замещении выполнить команду
  3. Заменить замещенную строку с выводом команды.
+0

Фантастический. Я забыл поставить команду ** e ** в конце, но сделал это после просмотра вашего ответа, и это сработало. Я пытался добавить случайный идентификатор от 1000 до 15000, когда SED соответствует строке. '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 '' – sgsi

0

Лучше результат для меня:

ls -1 | xargs -L1 -d "\n" CMD 
+0

Лучше, но не идеально. 'найти. -индекс 1-макс-1-конец 0 | xargs -0 command' будет обрабатывать случаи, когда вывод 'ls -1' неоднозначен; используйте '-printf '% P \ 0'', а не' -print0', если вы не хотите, чтобы ведущий '. /' на каждом. –

0

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 ... (см ответ Michael Aaron Сафьян S) (3.55s vs. 0.066s). Но для других команд ввода, таких как поиск, поиск, чтение из файла (tr \\n \\0 <file) или аналогичный, вам необходимо работать с xargs следующим образом.

Смежные вопросы