Come scoprire una nuova linea usando un ciclo for?


8

In vari punti del Web ho trovato:

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

tutto come sinonimi per varie newline / ritorni a capo ...

Ma in questa piccola sceneggiatura non riesco a riconoscere quando mi imbatto in una nuova riga: qualcuno può dirmi cosa dovrei controllare nella riga if?

#!/bin/bash

test="this is a
test"

for a in "$test"; do

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

echo "$a"

done

1
Ho una domanda stupida. Perché hai bisogno di fare questo? Se leggi l'input riga per riga cat | while read line; do ...; done, sai che c'era un ritorno a capo per ogni iterazione. Se il tuo input può essere un file \rsenza \n, trasforma il file tr '\r' '\n'durante l'elaborazione dell'input. Se avete solo bisogno di sapere se ci sono più linee: wc -l.
Nicerobot,

Benvenuto in Stack Exchange. Si prega di non modificare la domanda in questo modo, in quanto rende le risposte esistenti prive di significato. Dal momento che hai trovato un modo per risolvere il tuo problema, puoi pubblicarlo come risposta alternativa.
Gilles 'SO- smetti di essere malvagio' il

@nicerobot se non c'è nessuna newline, allora wc -lrestituirà 0; dovresti aggiungerlo come risposta
Arcege il

@lolfrog la soluzione non dovrebbe essere nella domanda, dovresti contrassegnare la risposta che ha la soluzione
Arcege,

Risposte:


6

Se usi direttamente le stringhe in un forciclo, funzionerà per parola (qui su una parola: l'intero contenuto di $testda quando è citato), non per carattere. È necessario utilizzare un whileciclo con readper analizzare lettera per lettera o per introdurre un parametro numerico che verrebbe ripetuto sulla stringa.

Inoltre, quando si utilizza read, è necessario assicurarsi che le nuove righe e gli spazi bianchi non vengano interpretati come delimitatori e di forzare la readlettura di un carattere alla volta.

Ecco una versione funzionante:

#!/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

È possibile sostituire $'\n'con $'\012'o $'\x0a', poiché rappresentano tutti lo stesso codice di nuova riga. Ma non è lo stesso di \015o \r- questo indica il ritorno a capo (ritorno all'inizio della riga). Sui sistemi Linux, le newline sono rappresentate utilizzando \n, ma su Windows, ad esempio, sono rappresentate da una sequenza di \r\ninvece. Ecco perché se avessi un file di testo da Windows, potresti rilevare anche le nuove righe cercando \r.


In breve, sta trasformando la sequenza di escape tra virgolette come \nnella sua rappresentazione in byte, quindi non è necessario inserire interruzioni di linea citate dall'aspetto sgradevole nell'istruzione del test.
rozcietrzewiacz,

4

Puoi controllare le newline in una variabile molto facilmente in bash con:

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

Trovo più conveniente usare:

declare -r EOL=$'\n' TAB=$'\t' # at top of script
..
if [[ $var = *$EOL* ]]; then # to test (no field-splitting in [[ )

1

Suggerirei di usare tre quindi test:

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

Il tr -cdrimuove tutto tranne i ritorno a capo / ritorni a capo. Se ci sono newline nel file, allora ci sarà l'output da cui il -ntest tornerà vero.


Ciò non funzionerà per i file che non contengono \rs poiché la sostituzione dei comandi rimuove i caratteri di fine riga finali ( "$(printf '\n\n\n\n\n')"è la stringa vuota).
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.