Как сохранить переводы строк в xargs -I {}

Как сохранить переводы строк в xargs -I {}

Следующий код извлекает несколько десятков строк в переменную, но каким-то образом они все помещаются в одну строку. То есть они теряют исходный символ новой строки:

ALL_FOUND_LINES=$(find "$TEMP" -type f -name "debug.log*" | xargs -I {} grep -F "STARTING HOST " {})

Есть ли способ сохранить символ новой строки в выражении, подобном приведенному выше?

решение1

Если вы тестируете это с помощью

echo $ALL_FOUND_LINES

то я не удивлен, что все новые строки исчезли, так как оболочка разделила бы значение на $ALL_FOUND_LINESпробелы, табуляции и новые строки (по умолчанию) на слова (а затем дополнительно расширила бы каждое слово посредством генерации имени файла (глоббинга)). Она делает это, так как расширение не заключено в кавычки. echoЗатем утилита получает список слов, которые она печатает в одной строке.

Лучшим тестом было бы

printf '%s\n' "$ALL_FOUND_LINES"

Обратите внимание на кавычки расширения переменной. Для выбора printfболее echoсм.Почему printf лучше, чем echo?.


Ваша команда может быть улучшена до

find "$TEMP" -type f -name 'debug.log*' -exec grep -h -F 'STARTING HOST ' {} +

Здесь, вместо того, чтобы передавать имена файлов в xargs, мы позволяем findвыполняться grepнапрямую на максимально debug.log*возможном количестве файлов одновременно. Обратите внимание, что избавление от xargsне решает вашу проблему с переводами строк, поскольку xargsне имеет к этому никакого отношения. Это немного ускорит процесс, поскольку потребует меньше вызовов grep.

Смотрите такжеПонимание опции -exec команды `find`.

Если вам нужно что-то сделать с каждой из найденных строк, то вы можете выполнить цикл по ним следующим образом:

find "$TEMP" -type f -name 'debug.log*' -exec grep -h -F 'STARTING HOST ' {} + |
while IFS= read -r line; do
    # use "$line" here (with quotes)
done

(или замените цикл while любым другим этапом обработки, который вам необходимо выполнить). Таким образом, нет необходимости хранить все данные в переменной в виде строки, разделенной символом новой строки.

Смотрите такжеПонимание «IFS= read -r line»

решение2

человек xargs

   -L max-lines
          Use at most max-lines nonblank input  lines  per  command  line.
          Trailing blanks cause an input line to be logically continued on
          the next input line.  Implies -x.

   -l[max-lines], --max-lines[=max-lines]
          Synonym for the -L option.  Unlike -L, the max-lines argument is
          optional.   If  max-lines  is not specified, it defaults to one.
          The -l option is deprecated since the POSIX  standard  specifies
          -L instead.

Связанный контент