文字列がエスケープシーケンス(\ n)で終わるかどうかを確認する方法

文字列がエスケープシーケンス(\ n)で終わるかどうかを確認する方法

x末尾の改行文字を持つ変数があります。

printf -v x 'hello\n'

最後の文字があるかどうかはxどうすればわかりますか\n

答え1

\n文字ではなく文字列の最後の文字を記述するので、その文字が単一文字(newlineASCIIとも呼ばれる)であるかどうかを検出する方法を探していますline feed。文字列が\2文字(バックスラッシュ)で終わるかどうかを検出したくありませんn

かなり最新バージョンのBashでこれを行う1つの方法は次のとおりです。

#!/usr/bin/env bash

printf -v x 'hello\n'

[[ "${x: -1:1}" == $'\n' ]] && echo "Ends in newline"

echo done

${x: -1:1}Bash の部分文字列拡張を使用して文字列の最後の文字を返します。マニュアルページの構文は、負の${parameter:offset:length}オフセットが文字列の先頭ではなく最後から始まることを示しています。また、さまざまな種類のパラメータ拡張との混同を避けるために、最初とスペースの間:にスペースが必要であると述べています。-1

$'\n'Bashの「一重引用符の特別なバリエーション」構文を使用して、「ANSI C標準」で指定された文字を表します。

このオプションは、組み込みコマンドでstdoutの代わりに指定された変数に出力を書き込むためにprintf使用されます。このオプションはすべてのシェルでは機能しない可能性があります(外部バイナリ-vでも機能しない)。文字はprintf直接printfサポートされ、\n「特殊バリアント」構文は必要ありません。

書かれているように、これは変数の終わりの改行でのみ機能しますが、これはあなたが必要とするものです。異なる制御文字および/または文字列の他の場所を特定するには、特定の要件に応じて異なる構文が必要です。

答え2

POSIXシェルでは:

case "$string" in
  (*'
')    echo The string ends in a newline character;;
  (*) echo It does not;;
esac

$'...'ksh93の引用形式をサポートする(そしてPOSIX標準の次のバージョンで指定される)bashを含むシェルで次のshコマンドを使用すると、読みやすくなります。

case "$string" in
  (*$'\n') echo The string ends in a newline character;;
       (*) echo It does not;;
esac

サポートされていないシェルの場合、他のオプションは$'...'改行文字をグローバル変数に格納することです。

NL='
'

または

eval "$(printf ' NL="\n" CR="\r" TAB="\t" FF="\f" BS="\b" BEL="\a" ')"

各制御文字の変数を構成し、以下を使用します。

case "$string" in
  (*"$NL") echo The string ends in a newline character;;
  (  *   ) echo It does not;;
esac

一部のシェル(最小ksh93、zsh、bash、mksh)では、次のこともできます。

if [[ "$string" = *$'\n' ]]; then
  echo The string ends in a newline character
else
  echo It does not;;
fi

パラメーターの最後の文字であるPOSIXlyを取得するには、パターン除去演算子を乱用する可能性があります。

if [ "${string#"${string%?}"}" = "$NL" ]; then
  echo The string ends in a newline character
else
  echo It does not;;
fi

zsh または yash では、次のことができます。

if [ "${string[-1]}" = "$NL" ]; then...

または、次のように単純化されましたzsh

if [[ $string[-1] = $'\n' ]]; then...

この配列はスパース配列で$var既に短縮されており、多次元配列をサポートし${var[0]}ているため、ksh93は文字列または配列分割に厄介な構文を導入しました。

if [[ ${string:${#string}-1} = $'\n' ]]; then...

bash(多次元配列はありませんが、kshから配列設計の大部分をコピーします)はこれを2.0で複製しました。

Bashでは、オフセットは負の数でもよく、最後から計算されます(または4.2で始まる長さも可能です)。しかし、${var:-default}Bourneシェルの他のすべてと同様に、算術式の後の最初の文字は(nor)に:はできません。or-または...が必要です。+${string: -1}${string:(-1)}S{string:0-1}

ksh93はこれをksh93mで複製し、mkshと同様にzshも最終的に${var:offset[:length]}ksh互換性のサポートを追加しました(zshのcshスタイルのサポートによりさらに制限がありましたが${var:modifiers})。

関連情報