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