Почему это «пока» цикла не распознает последнюю строку?

ответ Тердона perl , безусловно, элегантен, и я согласен: если цель состоит в том, чтобы все данные были отформатированы единообразно / согласованно, нет необходимости разделять линии нужно изменить. Если вам не нравится perl (или, что маловероятно, у вас его нет), вот sed решение:

sed -re 's/_[Ff]([0-9]+)[Rr]([0-9]+)_/_F00\1R00\2_/' \
                                          -e 's/_F0*([0-9]{3})R0*([0-9]{3})_/_F\1R\2_/'

Это можно ввести как целую одну строку (оставьте \ в конце первой строки). Признаюсь, это не так элегантно, как решение perl . Он работает в два этапа:

  • Добавьте 00 после каждого F или R (или f или r ) в шаблоне _ F номер_файла R номер_файла _ . Это изменяет однозначное число 8 на 008 , двузначное 08 на 0008 , и трехзначное число от 008 до 00008 .
    (На первом этапе также используются заглавные буквы f или r .)
  • После каждого F или R ] в шаблоне _ F номер_файла R номер_файла _ , удалите столько нулей, сколько стоит перед последними тремя цифрами. Таким образом, 008 остается без изменений, а 0008 и 00008 заменяются на 008 .

Если ваша версия sed не поддерживает параметр -r (использовать расширенные регулярные выражения), используйте

sed -e 's/_[Ff]\([0-9]*\)[Rr]\([0-9]*\)_/_F00\1R00\2_/' \
                                          -e 's/_F0*\([0-9]{3}\)R0*\([0-9]{3}\)_/_F\1R\2_/'

, используя \ (… \) вместо (…) и * вместо + . ( * и + не означают одно и то же, , но в данном случае они достаточно близки, если только нет строк со строками например _FR42_ или _F17R_ . Фактически, вы также можете использовать * вместо + в первой команде .)

Как использовать эти

  • сценарии опций sed InputFile
    или
    sed сценарии опций
    для обработайте входной файл и посмотрите результаты на экране.
  • сценарии параметров sed InputFile> output_file
    или
    sed сценарии параметров output_file
    для обработки входного файла и отправки результатов в новый файл.
  • sed -i сценарии параметров InputFile
    для обработки файла и изменения его на месте; т. Е. Отправить результаты обратно в исходный файл.
2
19.11.2018, 01:09
2 ответа

Введенный текст содержит неполную строку в качестве последней строки. Последняя строка не завершается символом новой строки.

while IFS= read -r line || [ -n "$line" ]; do
    printf '%s\n' "$line"
done <file

Приведенный выше цикл будет считывать неизмененные строки¹ (без удаления пробелов или интерпретации управляющих последовательностей с обратной косой чертой )из файла с именем fileи выводить их на стандартный вывод.

При чтении неполной строки readпроизойдет сбой, но $lineпо-прежнему будет содержать данные. Дополнительный тест -nобнаружит это, чтобы тело цикла могло вывести неполную строку. На следующей итерации readснова не удастся, а $lineбудет пустой строкой, что приведет к завершению цикла.


¹ при условии, что они не содержат символов NUL в оболочках, отличных от zsh, и при условии, что они не содержат последовательностей байтов, не являющихся частью допустимых символов в оболочке yash, оба из которых не должны происходить, если ввод является допустимым текстом, хотя этот отсутствующий разделитель строк в последней строке уже делает его недопустимым текстом.

14
27.01.2020, 21:52

Ввод в цикл чтения должен выполняться следующим образом:

cat /tmp/file | { cat ; echo ; } | while read -r line; do echo $line;  done

Это обработает все строки, включая последнюю.

Источник :Мой проект с открытым исходным кодомhttps://sourceforge.net/projects/command-output-to-html-table/

0
12.10.2021, 03:17

Теги

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