Shell
測試變數是否包含換行符(POSIX)
我知道有些 shell 接受這種測試:
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支持(截至 2018 年 2 月)。sh
至於您擁有的測試是否足夠,您已經對這兩種情況進行了測試,因此將測試所有程式碼路徑。
目前在 POSIX 規範中沒有明確規定:是否
*
匹配包含不形成有效字元的字節序列的字元串,或者 shell 變數是否可能包含這些字元串。在實踐中,除了
yash
其變數只能包含字元,並且除了 NUL 字節(沒有外殼但zsh
可以儲存在它們的變數中)之外,*$nl*
應該匹配任何包含的字元串,$nl
即使它們包含不形成有效的字節序列字元(如$'\x80'
在 UTF-8 中)。例如,某些
find
實現將無法與-name "*$nl*"
它們匹配,因此如果測試一個新的 shell,並且如果您打算處理不能保證是文本的內容(如文件名),您可能需要為其添加一個測試案例。與:test=$(printf '\200\n\200')
在 UTF-8 語言環境中。