変数に改行文字(POSIX)が含まれているかどうかをテストする

変数に改行文字(POSIX)が含まれているかどうかをテストする

私はいくつかのシェルがこの種のテストを可能にすることを知っています。

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

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

実行時:

$ bash ./script
yes no
  1. POSIXに対応するタスクは何ですか(ダッシュ)

  2. 次のテスト方法は信頼できますか?

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

答え1

変数に新しい行を入れてパターンマッチングを実行できます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

改行を作成する別の方法は次のとおりです。

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

明らかなコマンド置換は、置換が末尾の改行を削除するため、機能しません。

答え2

はい、

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

case(原則として、パターンとして扱われたくない限り、パターン内ですべての変数拡張を引用したいのですが、ここでは$nlワイルドカードが含まれていないため違いはありません。)

または

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

すべてがうまく機能し、POSIXと互換性がなければならず、これが私が使用するでしょう。 sを削除すると、(以前のBourneシェルでも機能します。

変数を設定する$nl別の方法:

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

気づく$'\n'POSIX規格の次のバージョンに含まれる予定。少なくともksh93、、、、 busybox 、およびFreeBSDでサポートされています(2018年2月現在)zshbashmkshsh

保持しているテストが十分かどうかについて両方のケースでテストしたので、すべてのコードパスがテストされます。

現在のPOSIX仕様に明示的に指定されていないことは、*有効な文字を形成しないバイト列が含まれる文字列を一致させるかどうか、またはシェル変数にこれらの文字列を含めることができるかどうかです。

実際には、変数に文字しか含めることができないことを除いて、NULバイト以外の文字列を含む文字列yash(シェルはできませんがzsh変数に​​格納できます)は、有効なバイト列を形成しない文字が含まれていても一致する必要があります。 (UTF-8など)。*$nl*$nl$'\x80'

たとえば、一部のfind実装は-name "*$nl*"一致しないため、新しいシェルをテストし、テキスト(ファイル名など)が保証されていない項目を処理したい場合は、これにテストケースを追加できます。 。次のように:

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

UTF-8ロケール。

関連情報