#bash #shell #echo #popen #xargs
#bash #оболочка #echo #popen #xargs
Вопрос:
Я пытался использовать xargs
для передачи аргументов в echo
:
[usr@linux scripts]$ echo {0..4} | xargs -n 1 echo
0
1
2
3
4
-n 1
гарантировал, что xargs
аргументы будут 1
передаваться echo
раз за разом в
Затем я хочу использовать этот аргумент дважды, однако результаты не те, которые я хотел:
[usr@linux scripts]$ echo {0..4} | xargs -I@ -n 1 echo @,@
0 1 2 3 4,0 1 2 3 4
-n 1
кажется отключенным, когда я добавил -I@
,
и это тот результат, который я хотел:
0,0
1,1
2,2
3,3
4,4
как я могу этого добиться?
———Поставка—————— Я использовал метод, рекомендованный @123 , однако есть еще один вопрос:
test.sh:
#!/bin/bash
a[0]=1
a[1]=2
echo "a[0] and a[1] : "${a[0]}, ${a[1]}
echo -n {0..1} | xargs -I num -d" " echo num,${a[num]},num
и это результат:
[usr@linux scripts]$ sh test.sh
a[0] and a[1] : 1, 2
0,1,0
1,1,1
вы можете видеть, что массив a
возвращает не то значение, которое я хотел :<
И как я могу решить эту проблему?
Комментарии:
1.
echo -n {0..4} | xargs -I@ -d' ' echo @,@
?printf "%sn" {0..4} | xargs -I@ echo @,@
?2. не могли бы вы взглянуть на этот вопрос, который я только что обновил? При использовании аргументов все еще возникают некоторые вопросы: (@123
3. Расширение оболочки происходит до того, как xargs его увидит, поэтому оно всегда оценивается как
${a[num]}
aka${a[0]}
. можно было бы сделать что-то глупое вродеxargs -I num -d" " bash -c 'echo $num' "${a[@]}"
но, вероятно, есть лучший способ достичь любой вашей конечной цели.4. @123 У меня просто есть некоторые сомнения по поводу
bash -c 'echo $num' "${a[@]}"
того, как насчет первыхecho $num
работ? Похоже, что$num
заменяется@
в${a[@]}
?5. И я только что попробовал подобную команду
a[0]=x;a[1]=y;num=1;bash -c 'echo $num' "{a[@]}"
, результат, который я ожидал, равен y, однако результат просто пустой.
Ответ №1:
Если вы не можете изменить формат ввода, вы могли бы установить разделитель на пробел:
$ echo -n {0..4} | xargs -d " " -I@ echo @,@
0,0
1,1
2,2
3,3
4,4
В противном случае измените входные данные, чтобы разделить токены новой строкой:
$ printf "%sn" {0..4} | xargs -I@ echo @,@
0,0
1,1
2,2
3,3
4,4
Причина такого синтаксиса объясняется в man xargs
-I replace-str
Replace occurrences of replace-str in the initial-arguments with names read from
standard input. Also, unquoted blanks do not terminate input items; instead the sep‐
arator is the newline character. Implies -x and -L 1.
Поэтому вы должны вручную установить разделитель на пробел, если хотите разграничить поля.
Комментарии:
1. @123: Я не совсем уверен, почему версия OP не работает. По-видимому,
xargs
разбивает строку ввода на пробелы, когда-I
опция не используется, но с-I
она обрабатывает строку как один аргумент. Я не смог найти хорошего объяснения этого на странице руководства…2. Под
-I
>Also, unquoted blanks do not terminate input items; instead the separator is the newline character.
3. Не могли бы вы взглянуть на вопрос, который я только что обновил? Все еще есть некоторые вопросы в использовании аргументов:(
4. @springcc: повторите редактирование, причина, по которой это не работает, заключается в том, что переменные заменяются перед выполнением xargs, поэтому
${a[num]}
получает первое значение массива, посколькуvar
оно не определено. Вы могли бы решить это с помощью eval, но, вероятно, есть лучшее решение…5. @springcc Вы столкнулись с давно известной проблемой. Вы не можете использовать
xagrs -I
замену в качестве итератора массива. Итак, вам нужно вызвать некоторую подоболочку черезeval
или просто с помощьюbash -c
. Итак, вам нужно будет экспортировать свой массив, но… Вы не можете экспортировать массив в bashИз manpage:
Array variables may not (yet) be exported.
На самом деле, для этого есть несколько способов, но лучший способ — настроить логику вашего скрипта и предоставить xargs только обычные переменные.