Ahmad Ismail Asked: 2023-06-05 12:05:32 +0800 CST2023-06-05 12:05:32 +0800 CST 2023-06-05 12:05:32 +0800 CST 如何检查字符串是否以转义序列 (\n) 结尾 772 我有一个x带有尾随换行符的变量。 printf -v x 'hello\n' 如何找出的最后一个字符x是\n? bash 2 个回答 Voted Best Answer Sotto Voce 2023-06-05T13:24:19+08:002023-06-05T13:24:19+08:00 您描述的是字符串的最后一个字符,而不是字符,因此您正在寻找一种方法来检测它是否是单个字符\n(newline也就是 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选项将输出写入指定变量而不是标准输出。此选项可能并非在所有 shell 中都可用(并且在外部printf二进制文件中不可用)。 直接printf支持没有“特殊变体”语法的字符。\n 如所写,这仅适用于变量末尾的换行符,但这就是您所要求的。检查字符串中的其他控制字符和/或其他位置将需要不同的语法,具体取决于您的特定需要。 Stéphane Chazelas 2023-06-05T16:06:25+08:002023-06-05T16:06:25+08:00 在任何 POSIX shell 中: case "$string" in (*' ') echo The string ends in a newline character;; (*) echo It does not;; esac 在包括支持 ksh93 引号形式的 bash 在内的 shell 中$'...'(并且将在下一版本的 POSIX 标准中指定sh),可以通过以下方式使其更易于阅读: 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是 already 的缩写${var[0]},而且它支持多维数组,所以 ksh93 引入了一种笨拙的字符串或数组切片语法: if [[ ${string:${#string}-1} = $'\n' ]]; then... bash(它没有多维数组,但在其他方面从 ksh 复制了它的大部分数组设计)在 2.0 中复制了它。 在 bash 中,偏移量也可以是负数以从末尾开始计数(甚至是从 4.2 开始的长度)。但是,正如Bourne shell 中已经存在的其他内容一样,算术表达式中不能是(nor )${var:-default}之后的第一个字符,因此您需要or或...:-+${string: -1}${string:(-1)}S{string:0-1} ksh93 将其复制回 ksh93m,zsh 最终还添加了对那些${var:offset[:length]}与 ksh 兼容的支持(尽管有更多限制,因为 zsh 支持 csh-style ${var:modifiers}),mksh 也是如此。
您描述的是字符串的最后一个字符,而不是字符,因此您正在寻找一种方法来检测它是否是单个字符
\n
(newline
也就是 ASCII 中的line feed
)。您不希望检测字符串是否以两个字符\
(反斜杠)和 结尾n
。这是在相当现代的 Bash 版本中执行此操作的一种方法:
${x: -1:1}
使用 Bash 的子字符串扩展返回字符串的最后一个字符。手册页中的语法是${parameter:offset:length}
并指出负偏移量从字符串的结尾而不是开头开始。:
它还指出,第一个和之间需要一个空格,-1
以避免与不同类型的参数扩展混淆。$'\n'
使用 Bash 的“单引号的特殊变体”语法来表示“ANSI C 标准”指定的字符。内置
printf
命令使用-v
选项将输出写入指定变量而不是标准输出。此选项可能并非在所有 shell 中都可用(并且在外部printf
二进制文件中不可用)。 直接printf
支持没有“特殊变体”语法的字符。\n
如所写,这仅适用于变量末尾的换行符,但这就是您所要求的。检查字符串中的其他控制字符和/或其他位置将需要不同的语法,具体取决于您的特定需要。
在任何 POSIX shell 中:
在包括支持 ksh93 引号形式的 bash 在内的 shell 中
$'...'
(并且将在下一版本的 POSIX 标准中指定sh
),可以通过以下方式使其更易于阅读:不支持的 shell 的另一个选项
$'...'
是将换行符存储在全局变量中:或者
为每个控制字符组成一个变量并使用:
在一些 shell 中(至少是 ksh93、zsh、bash、mksh),您还可以:
要获取参数的最后一个字符,POSIXly,您可以滥用模式剥离运算符:
在 zsh 或 yash 中,你会这样做:
或简化为
zsh
:因为它的数组是稀疏数组,
$var
是 already 的缩写${var[0]}
,而且它支持多维数组,所以 ksh93 引入了一种笨拙的字符串或数组切片语法:bash(它没有多维数组,但在其他方面从 ksh 复制了它的大部分数组设计)在 2.0 中复制了它。
在 bash 中,偏移量也可以是负数以从末尾开始计数(甚至是从 4.2 开始的长度)。但是,正如Bourne shell 中已经存在的其他内容一样,算术表达式中不能是(nor )
${var:-default}
之后的第一个字符,因此您需要or或...:
-
+
${string: -1}
${string:(-1)}
S{string:0-1}
ksh93 将其复制回 ksh93m,zsh 最终还添加了对那些
${var:offset[:length]}
与 ksh 兼容的支持(尽管有更多限制,因为 zsh 支持 csh-style${var:modifiers}
),mksh 也是如此。