一部のシェルがこの種のテストを受け入れることは知っています。
t() { [[ $var == *$'\n'* ]] && res=yes || res=no
printf '%s ' "$res";
}
var='ab
cd'
t
var='abcd'
t
echo
実行時:
$ bash ./script
yes no
POSIX(ダッシュ)と同等の機能とは
以下は信頼できるテスト方法ですか?
nl='
'
t() { case "$var" in
*$nl* ) res=yes ;;
* ) res=no ;;
esac
printf '%s ' "$res"
}
var='ab
cd'
t
var='abcd'
t
echo
変数にハード改行を入れて、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}
末尾の改行は置換によって削除されるため、明らかなコマンド置換は機能しません。
はい、
nl='
'
case $var in
(*"$nl"*) echo yes;;
(*) echo no;;
esac
(原則として、case
パターン内のすべての変数展開をパターンとして扱いたい場合を除いて引用します。ただし、ここでは$nl
にはワイルドカードが含まれていないため、違いはありません) 。
または
case $var in
(*'
'*) echo yes;;
(*) echo no;;
esac
すべてが機能し、POSIXに準拠している必要があります。 (
sを削除すると、古いBourne Shellでも機能します。
$nl
変数を設定する別の方法:
eval "$(printf 'nl="\n"')"
$'\n'
は、POSIX標準の次のバージョンに含まれる予定です であることに注意してください。少なくともksh93
、zsh
、bash
、mksh
、busybox、FreeBSD sh
で既にサポートされています(2018年2月現在)。
あなたが持っているテストが十分であるかどうかに関しては、両方のケースのテストがあり、すべてのコードパスをテストすることになります。
現在、POSIX仕様で明確に指定されていないものがあります。*
が、有効な文字を形成しないバイトシーケンスを含む文字列と一致するかどうか、またはシェル変数にそれらの文字列が含まれるかどうかです。
実際には、変数に文字のみを含めることができるyash
とNULバイト(zsh
以外の変数は変数に格納できない)を除いて、*$nl*
は有効な文字を形成しないバイトのシーケンスが含まれている場合でも、$nl
を含む文字列(UTF-8の$'\x80'
など)。
たとえば、一部のfind
実装はそれらの-name "*$nl*"
との一致に失敗するため、新しいシェルをテストする場合、およびテキストであることが保証されていないもの(ファイル名など)を処理する場合は、そのためのテストケースを追加したいかもしれません。と同じように:
test=$(printf '\200\n\200')
uTF-8ロケールで。