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


8

一部のシェルはこの種のテストを受け入れることを知っています:

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
    

回答:


12

変数にハード改行を入れて、とパターン一致させることができます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}

後続の改行は置換によって削除されるため、明らかなコマンド置換は機能しません。


5

はい、

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標準の次のバージョンに含まれる予定であることに注意してください。それはすでにによってサポートされていますksh93zshbashmksh、busyboxのとFreeBSD sh少なくとも(2018年2月現在)。

あなたが持っているテストが十分であるかどうかに関しては、両方のケースのテストがあり、すべてのコードパスをテストすることになります。

現在、POSIX仕様で明確に指定され*ていないものがあります。有効な文字を形成しないバイトシーケンスを含む文字列と一致するかどうか、またはシェル変数にそれらの文字列が含まれるかどうかです。

実際には、yashその変数に文字のみを含めることができること、およびNULバイト(シェルにはないがzsh変数に格納できる)を除いて、有効な形式ではないバイトのシーケンスが含ま*$nl*$nlている場合でも、含む文字列と一致する必要があります文字($'\x80'UTF-8など)。

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

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

UTF-8ロケールで。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.