如何检查字符串是否以转义序列 (\n) 结尾

如何检查字符串是否以转义序列 (\n) 结尾

x我有一个带有尾随换行符的变量。

printf -v x 'hello\n'

如何判断 的最后一个字符是否x\n

答案1

您描述的是字符串的最后一个字符,而不是字符,因此您正在寻找一种方法来检测它是否是单个字符\nnewline也称为 ASCII 中的line feed)。您不想检测字符串是否以两个字符\(反斜杠)和结尾n

这是在相当现代的 Bash 版本中执行此操作的一种方法:

#!/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 标准”指定的字符。

内置printf命令使用该-v选项将输出写入指定变量而不是 stdout。此选项可能不适用于所有 shell(并且不适用于外部printf二进制文件)。 直接printf支持字符,\n无需“特殊变体”语法。

正如所写,这仅适用于变量末尾的换行符,但这就是您所要求的。检查字符串中的其他控制字符和/或其他位置将需要不同的语法,具体取决于您的特定需求。

答案2

在任何 POSIX shell 中:

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

在包括支持$'...'ksh93 引用形式(并且将在 POSIX 标准的下一版本中指定sh)的 bash 的 shell 中,可以使用以下命令更容易阅读:

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

对于不支持的 shell,其他选项$'...'是将换行符存储在全局变量中:

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

在一些 shell 中(至少是 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 shell 中的其他内容一样,算术表达式中后面的第一个字符:不能是 a -(nor ),因此您需要or or ...+${string: -1}${string:(-1)}S{string:0-1}

ksh93 在 ksh93m 中复制了这一点,zsh 最终还添加了对${var:offset[:length]}与 ksh 兼容的支持(尽管由于 zsh 支持 csh 样式而具有更多限制${var:modifiers}),mksh 也是如此。

相关内容