Применение команд к спискам

Я полагаю, что ошибка, которую вы видите, может быть cppcheckзапущенной сMakefile(или другим файлом исходного кода не -C или не -C++ в текущем каталоге )в качестве входного файла.

Я предлагаю вам вместо установки SOURCESна !(Tests)указать фактические файлы исходного кода программы, на которой вы хотите запустить cppcheck.

1
23.09.2019, 19:46
5 ответов

Общее решение, которое будет работать, будет экспортировать 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для правильной работы с файлами, имена которых содержат пробелы.

0
27.01.2020, 23:17

Все, что касается чистых функций и каррирования, а что нет, хорошо для языка с первоклассными функциями, но со сценариями оболочки, конвейеры — это то, что вам следует искать.

Когда дело доходит до того, что вы явно должны сказать :взять строку из ввода, выполнить X, вывести, вам нужно сделать шаг назад и повторно -изучить, что вы делаете. Большинство стандартных инструментов автоматически берут строки из ввода, выполняют X и выводят, поэтому обычно вам просто нужно получить правильный инструмент и правильный X. Так что, если вы окажетесь в ситуации, когда вы берете строку из ввода, используйте ее в качестве ввода для инструмент, который уже может брать строки из ввода, а затем захватывать вывод этой команды и повторно использовать его для вывода... что-то не так.

В данном случае это просто sed, где X равно 's/begin-\([0-9]*\).end/\1/'.

Кроме того, примечание:echo $(sed...)бессмысленно, просто сделайте sed...напрямую. Вы фиксируете вывод, используя подстановку команд, а затем... просто снова используете его в качестве вывода.

1
27.01.2020, 23:17

Чтобы применить функцию к списку, вы просто перебираете его:

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
...
3
27.01.2020, 23:17

Если у вас есть список, вы часто можете выиграть от параллельного выполнения команд:

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
0
27.01.2020, 23:17

Похоже, вы хотите получить целое число 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для каждого файла, содержащего определенную строку.

0
27.01.2020, 23:17

Теги

Похожие вопросы