Как открыть новую строку, используя цикл for?

9

В разных местах в Интернете я нашел:

\015 
\012
\x0a - hex
\n
\r

все как синонимы для различных новых строк / возвратов каретки ...

Но в этом небольшом сценарии я не могу распознать, когда сталкиваюсь с новой строкой - может кто-нибудь сказать мне, что я должен проверять в строке if?

#!/bin/bash

test="this is a
test"

for a in "$test"; do

        if [[ "$a" == '\012' ]] ; then
                echo "FOUND NEWLINE"
        fi

echo "$a"

done
lolfrog
источник
1
У меня тупой вопрос. Зачем тебе это нужно? Если вы читаете входные данные построчно cat | while read line; do ...; done, вы знаете, что для каждой итерации был возврат каретки. Если ваши входные данные могут быть файлами \rбез \n, просто преобразуйте файл tr '\r' '\n'во время обработки ввода. Если вам просто нужно знать , если есть несколько строк: wc -l.
nicerobot
Добро пожаловать в Stack Exchange. Пожалуйста, не редактируйте свой вопрос таким образом, так как это делает существующие ответы бессмысленными. Поскольку вы нашли способ решить свою проблему, вы можете опубликовать его как альтернативный ответ.
Жиль "ТАК - перестань быть злым"
@nicerobot, если нет новой строки вообще, то wc -lвернет 0; Вы должны добавить это как ответ
Arcege
@ lolfrog решение не должно быть в вопросе, вы должны отметить ответ, который имеет решение
Arcege

Ответы:

6

Если вы непосредственно используете строки в forцикле, он будет работать для каждого слова (здесь одно слово: весь контент, $testпоскольку он указан в кавычках), а не для каждого символа. Вам нужно использовать whileцикл с read, чтобы анализировать букву за буквой, или вводить числовой параметр, который будет перебирать строку.

Кроме того, при использовании readнеобходимо убедиться, что символы новой строки и пробелы не интерпретируются как разделители, и заставить readчитать один символ за раз.

Вот рабочая версия:

#!/bin/bash

test="this is a
test"

printf %s "$test" | while IFS= read -r -N 1 a; do

        if [[ "$a" == $'\n' ]] ; then
                echo "FOUND NEWLINE"
        fi

printf %s "$a"

done

Вы можете заменить $'\n'на $'\012'или $'\x0a', так как все они представляют один и тот же код новой строки. Но это не то же самое, что \015или \r- это означает возврат каретки (возврат к началу строки). В системах Linux переводы строки представлены с использованием \n, но в Windows, например, они представлены последовательностью \r\nвместо. Вот почему, если у вас есть текстовый файл из Windows, вы можете обнаружить новые строки, также выполнив поиск \r.

rozcietrzewiacz
источник
Короче говоря, он превращает экранированную заключенную в кавычки последовательность, как \nв ее байтовое представление, так что вам не нужно помещать уродливые, заключенные в кавычки разрывы строк в вашем операторе test.
rozcietrzewiacz
4

Вы можете легко проверить наличие новых строк в переменной с помощью bash:

[[ $var = *$'\n'* ]]

Я считаю более удобным использовать:

declare -r EOL=$'\n' TAB=$'\t' # at top of script
..
if [[ $var = *$EOL* ]]; then # to test (no field-splitting in [[ )
steveL
источник
1

Я бы предложил использовать, trа затем test:

if [ -n "$(tr -cd '\n\r' < datafile)" ]; then
    echo "NEWLINE FOUND"
fi

tr -cdУдаляет все , кроме перевода строки / возврат каретки. Если в файле есть новые строки, то будет вывод, из которого -nтест вернет true.

Arcege
источник
Это не будет работать для файлов, не содержащих \rs, потому что подстановка команд удаляет завершающие символы новой строки ( "$(printf '\n\n\n\n\n')"это пустая строка).
Стефан Шазелас