Для сопоставления содержимого переменной оболочки в bash
, zsh
или ksh93
:
re='^[0-9]+(,[0-9]+)*$'
[[ $string =~ $re ]] && echo matches
POSIXly:
case $string in
("" | *[!,0-9]* | ,* | *, | *,,*) ;;
(*) echo matches;;
esac
Bournely:
expr " $string" : ' [0-9]\{1,\}\(,[0-9]\{1,\}\)*$' > /dev/null &&
echo matches
Для сопоставления строк ввода:
grep -xE '[0-9]+(,[0-9]+)*'
Мы используем +
(или эквивалент BRE \ {1, \}
) для сопоставления 1 или более цифр. *
соответствует 0 или более.
Да, -I
работает только с одним аргументом за раз. С -I
ввод также разбирается на аргументы иначе, чем без (с использованием -n
или без ).
С помощью -I{}
вы получаете слово для каждой не -пустой строки (, за исключением того, что по-прежнему можно вставлять новую строку, заключая ее в кавычки с обратной косой чертой ), с начальными, но не конечными пробелами (список которых зависит от реализации и локали для некоторых удаленных ). Котировки ("
, '
и \
по-прежнему обрабатываются, но не так, как sh
хотя ).
Без -I{}
слова являются пробелами (, по крайней мере, с разделителями SPC, TAB и NL )и обрабатываются кавычки.
Сравните:
$ printf ' a "b c" \n' | xargs -n1 printf '<%s>\n'
<a>
<b c>
$ printf ' a "b c" \n' | xargs -I{} printf '<%s>\n' {}
<a b c >
IMO, xargs
— это немного беспорядок, единственные надежные/полезные способы его использования — с расширениями -0
и -d
GNU.
Если вы хотите запустить команду с более чем одним аргументом за раз и использовать разные держатели места -для каждого, лучше всего использоватьsh
:
xargs < filelist -r -n2 sh -c 'printf "1: %s\n2: %s\n" "$1" "$2"' sh
Здесь xargs
передает 2 аргумента за раз в sh
, а sh
занимает место, занимаемое "$1"
и"$2"
(см. также "$@"
для передачи всех аргументов сразу ).
Это при токенизации слов по умолчанию xargs
. Если filelist
должен содержать один файл в строке, вы должны использовать -d '\n'
GNU xargs
.
Для вашего примера grep
вам не нужны ни -n
, ни -I
, просто:
xargs < filelist grep mystring
Затем xargs
передаст как можно больше аргументов вgrep
(аргументы добавляются в конце ). Мы можем обойтись без -r
здесь (расширения GNU )как будто filelist
все пустое, все еще работающее grep
без файловых аргументов (которое -r
предотвращает )должно быть безвредным, поскольку оно будет искать mystring в конце filelist
.
Однако вы можете использовать параметр -H
GNU grep
или запустить его как:
xargs < filelist grep mystring /dev/null
, чтобы убедиться, что grep
всегда печатает имя файла, когда находит совпадение, даже если filelist
содержит только одно слово.
GNU Parallel исправил эту проблему. -X будет включать контекст:
$ seq 1 10 | parallel -j1 -qX echo "<{}>"
<1> <2> <3> <4> <5> <6> <7> <8> <9> <10>
-м не будет:
$ seq 1 10 | parallel -j1 -qm echo "<{}>"
<1 2 3 4 5 6 7 8 9 10>