Я полагаю, что ошибка, которую вы видите, может быть cppcheck
запущенной сMakefile
(или другим файлом исходного кода не -C или не -C++ в текущем каталоге )в качестве входного файла.
Я предлагаю вам вместо установки SOURCES
на !(Tests)
указать фактические файлы исходного кода программы, на которой вы хотите запустить cppcheck
.
Общее решение, которое будет работать, будет экспортировать f()
и использовать его. с xargs
. Например:
$ f()
> {
> echo param is: "$1"
> }
$ export -f f
$ grep -l string2 * | xargs -n1 bash -c 'f "$@"' {}
param is: FILE
Вам нужно использовать bash -c...
, потому что xargs
не знает о f()
, потому что, как описано здесь:
Normally, xargs will exec the command you specified directly, without invoking a shell.
И рассмотрите возможность использования -Z
с grep
вместе -0
с xargs
для правильной работы с файлами, имена которых содержат пробелы.
Все, что касается чистых функций и каррирования, а что нет, хорошо для языка с первоклассными функциями, но со сценариями оболочки, конвейеры — это то, что вам следует искать.
Когда дело доходит до того, что вы явно должны сказать :взять строку из ввода, выполнить X, вывести, вам нужно сделать шаг назад и повторно -изучить, что вы делаете. Большинство стандартных инструментов автоматически берут строки из ввода, выполняют X и выводят, поэтому обычно вам просто нужно получить правильный инструмент и правильный X. Так что, если вы окажетесь в ситуации, когда вы берете строку из ввода, используйте ее в качестве ввода для инструмент, который уже может брать строки из ввода, а затем захватывать вывод этой команды и повторно использовать его для вывода... что-то не так.
В данном случае это просто sed
, где X равно 's/begin-\([0-9]*\).end/\1/'
.
Кроме того, примечание:echo $(sed...)
бессмысленно, просто сделайте sed...
напрямую. Вы фиксируете вывод, используя подстановку команд, а затем... просто снова используете его в качестве вывода.
Чтобы применить функцию к списку, вы просто перебираете его:
list=(one two 'twenty one' banana)
f() {
echo "This is f applied to '$1'"
}
for item in "${list[@]}"
do
f "$item"
done
Если у вас есть (разделенный пробелом )список, вы можете преобразовать его в массив (в список )или пройти через него. Обратите внимание, что здесь любой элемент в списке без кавычек, который содержит подстановочный знак (*
, ?
, [
... ]
), будет оцениваться как обычно в контексте текущего каталога, поэтому нам нужно отключить это действие. во-первых (уже одно это является веской причиной для использования массивов/списков, а не строки элементов, разделенных пробелами -):
text='one two twenty-one banana'
OIFS="$IFS" IFS=' ' OSHELLOPTS="$SHELLOPTS"
set -o noglob
for item in $text
do
f "$item"
done
IFS="$OIFS"
[[ ! "$OSHELLOPTS:" =~ [=:]noglob: ]] && set +o noglob
Вариантов предостаточно; вот один со списком, разделенным двоеточием -:
text='one:two:twenty one:banana'
OIFS="$IFS" IFS=':' OSHELLOPTS="$SHELLOPTS"
set -o noglob
...
Если у вас есть список, вы часто можете выиграть от параллельного выполнения команд:
env_parallel --session
f () { echo $(sed 's/begin-\([0-9]*\).end/\1/' <<<$1) ;}
grep -l "stringToBeSearched" * | env_parallel f
или:
f () { echo $(sed 's/begin-\([0-9]*\).end/\1/' <<<$1) ;}
export -f f
grep -l "stringToBeSearched" * | parallel f
Похоже, вы хотите получить целое число N
в имени файла begin-N.end
для каждого такого имени файла, содержащего строку stringToBeSearched
.
Это можно сделать в простом цикле:
for filename in begin-*.end; do
if grep -qF 'stringToBeSearched' "$filename"; then
N=${filename%.end}
N=${N#begin-}
printf '%s\n' "$N"
fi
done
Дело в том, что мы не перебираем текст . Текст, содержащий имена файлов (, что является выводом grep -l
), очень плохо кодирует все возможные имена файлов в системе Unix, особенно имена файлов, содержащие символы новой строки.
Вместо этого мы позволяем шаблону глобуса begin-*.end
расшириться до правильного списка и перебираем его, проверяя каждый элемент списка с помощью grep
, а затем извлекая целое число, когда находим совпадение.
Очевидно, что вы могли бы обернуть это в функции, если хотите:
test_files () {
local func="$1"; shift
local string="$1"; shift
# Looks for the string "$string" in all given files.
# Calls "$func" with each pathname that contains the string.
for pathname do
if grep -qF "$string" "$pathname"; then
"$func" "$pathname"
fi
done
}
foo () {
# Takes a string on the form "begin-N.end" and
# extracts and prints "N".
local tmp="${1%.end}"
printf '%s\n' "${tmp#begin-}"
}
test_files foo stringToBeSearched begin-*.end
Это более или менее использует простую форму «обратного вызова», посредством которой foo
вызывается test_files
для каждого файла, содержащего определенную строку.