Verifica se la variabile contiene newline (POSIX)


8

So che alcune shell accettano questo tipo di test:

t() { [[ $var == *$'\n'* ]] && res=yes || res=no
      printf '%s ' "$res";
    }

var='ab
cd'
t
var='abcd'
t
echo

in esecuzione:

$ bash ./script
yes no
  1. Qual è l'equivalente funzionante POSIX (trattino)

  2. Di seguito è un modo affidabile per testare?

    nl='
    '
    
    t() {  case "$var" in
               *$nl* ) res=yes ;;
               * ) res=no ;;
           esac
           printf '%s ' "$res"
         }
    
    var='ab
    cd'
    t
    var='abcd'
    t
    echo

Risposte:


12

È possibile inserire una nuova riga rigida in una variabile e corrispondere al modello con case.

$ cat nl.sh
#!/bin/sh
nl='
'
case "$1" in
    *$nl*)  echo has newline ;;
    *)      echo no newline  ;;
esac

$ dash nl.sh $'foo\nbar'
has newline
$ dash nl.sh $'foobar'
no newline

Il modo alternativo di creare la nuova riga è qualcosa del genere:

nl=$(printf "\nx"); nl=${nl%x}

La sostituzione del comando ovvio non funziona perché la sostituzione di nuove righe viene rimossa dalla sostituzione.


5

Sì,

nl='
'
case $var in
  (*"$nl"*) echo yes;;
  (*)       echo no;;
esac

(per principio, mi piace citare tutte le espansioni variabili all'interno del casemodello a meno che non voglia che vengano trattate come modello, anche se qui non fa differenza in quanto $nlnon contiene caratteri jolly).

o

case $var in
  (*'
'*) echo yes;;
  (*) echo no;;
esac

Dovrebbero funzionare tutti e sono conformi a POSIX, e cosa vorrei usare per quello. Se rimuovi la (s, funzionerebbe anche nella vecchia shell Bourne.

Per un altro modo di impostare la $nlvariabile:

eval "$(printf 'nl="\n"')"

Si noti che $'\n'è previsto l'inclusione nella prossima versione dello standard POSIX . E 'già supportato da ksh93, zsh, bash, mksh, busybox e FreeBSD shalmeno (a partire da febbraio 2018).

Per quanto riguarda se il test che hai è sufficiente, hai un test per entrambi i casi, quindi verificherei tutti i percorsi del codice.

Al momento c'è qualcosa che non è chiaramente specificato nelle specifiche POSIX: se *corrisponde a una stringa che contiene sequenze di byte che non formano caratteri validi o se le variabili della shell possono contenere quelle stringhe.

In pratica, a parte le yashcui variabili possono contenere solo caratteri e a parte i byte NUL (che non hanno shell ma zshpossono memorizzare nelle loro variabili), *$nl*dovrebbero corrispondere a qualsiasi stringa che contiene $nlanche se contengono sequenze di byte che non formano valide personaggi (come $'\x80'in UTF-8).

Alcune findimplementazioni, ad esempio, non riuscirebbero a combaciare con -name "*$nl*"esse, quindi se testate una nuova shell e se intendete gestire cose che non sono garantite come testo (come i nomi di file), potreste voler aggiungere un caso di prova. Come con:

test=$(printf '\200\n\200')

in una locale UTF-8.

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.