ChatGPT解决这个技术问题 Extra ChatGPT

如何在 Bash 中比较字符串

如何将变量与字符串进行比较(如果它们匹配,则执行某些操作)?


P
Peter Mortensen

在 if 语句中使用变量

if [ "$x" = "valid" ]; then
  echo "x has the value 'valid'"
fi

如果您想在它们不匹配时执行某些操作,请将 = 替换为 !=。您可以在各自的文档中阅读有关 string operationsarithmetic operations 的更多信息。

为什么我们在 $x 周围使用引号?

您需要 $x 周围的引号,因为如果它为空,您的 Bash 脚本会遇到语法错误,如下所示:

if [ = "valid" ]; then

== 运算符的非标准使用

请注意,Bash 允许 == 用于与 [ 相等,但 this is not standard

使用第一种情况,其中 $x 周围的引号是可选的:

if [[ "$x" == "valid" ]]; then

或使用第二种情况:

if [ "$x" = "valid" ]; then

这与 Unexpected operator error 中给出的已接受答案有何关系?我在使用 [ "$1" == "on" ] 时遇到了同样的错误。将其更改为 [ "$1" = "on" ] 解决了问题。
需要空格。
@JohnFeminella 在 bash 脚本中编写时,它应该有一个 = 而不是两个。
@user13107 那么您可能使用的是 sh,而不是 bash。这是关于 bash 的问题。
值得注意的是,您不能使用 [ $x -eq "valid" ]-eq 是整数的比较运算符,而不是字符串。
P
Peter Mortensen

或者,如果您不需要 else 子句:

[ "$x" == "valid" ] && echo "x has the value 'valid'"

如果你确实需要一个 else 子句并且想要做一个疯狂的单行: [ "$x" == "valid" ] && echo "valid" ||回显“无效”
@MattWhite:这通常是个坏主意,因为 echo 可能会失败。
@gniourf_gniourf,没问题,使用 [ "$X" == "valid" ] || ( echo invalid && false ) && echo "valid"
@12431234123412341234123 { echo invalid && false; }( echo invalid && false ) 更有效,因为它避免了为不必要的 subshell 付费。
在 POSIX sh 中, == 代替 = 是未定义的。 [SC2039]
K
Karl Nicoll
a="abc"
b="def"

# Equality Comparison
if [ "$a" == "$b" ]; then
    echo "Strings match"
else
    echo "Strings don't match"
fi

# Lexicographic (greater than, less than) comparison.
if [ "$a" \< "$b" ]; then
    echo "$a is lexicographically smaller then $b"
elif [ "$a" \> "$b" ]; then
    echo "$b is lexicographically smaller than $a"
else
    echo "Strings are equal"
fi

笔记:

if 和 [ 和 ] 之间的空格很重要 > 和 < 是重定向运算符,因此对于字符串,分别使用 \> 和 \< 对其进行转义。


感谢字符串字母顺序比较
我的问题是 $a 实际上有 " " 作为字符串文字值的一部分,因此我必须使用转义字符到 $b 来比较值。我在运行 bash -x ./script.sh 后能够找到它, -x 标志允许您查看每次执行的值并有助于调试。
请注意,字母顺序比较不是 POSIX 标准化的,因此不能保证在非 GNU 平台/非 bash shell 上工作。只有 pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html 处的操作保证是可移植的。
A
Abdull

要将字符串与通配符进行比较,请使用:

if [[ "$stringA" == *"$stringB"* ]]; then
  # Do something here
else
  # Do something here
fi

重要的是通配符只能用在右边!另请注意通配符周围缺少的 "。 (顺便说一句:通配符+1!)
扩展 $stringB 必须被引用(顺便说一下,左侧不需要被引用):if [[ $stringA = *"$stringB"* ]]; then
我正在尝试对文件路径中的文件名使用相同的通配符逻辑。但这对我不起作用。尝试了此处提供的所有不同的通配符字符串。但它总是去其他情况。在我的例子中,stringA 是文件路径 /tmp/file,而 stringB 是“文件”。
C
Community

我不得不在某一点上不同意其中一项评论:

[ "$x" == "valid" ] && echo "valid" || echo "invalid"

不,这不是一个疯狂的单行者

只是它看起来像一个,嗯,外行......

在某种程度上,它使用通用模式作为一种语言;

在你学会了语言之后。

其实读起来很爽

它是一个简单的逻辑表达式,有一个特殊的部分:逻辑运算符的惰性求值。

[ "$x" == "valid" ] && echo "valid" || echo "invalid"

每个部分都是一个逻辑表达式;第一个可能是真或假,其他两个总是正确的。

(
[ "$x" == "valid" ] 
&&
echo "valid"
)
||
echo "invalid"

现在,当它被评估时,第一个被检查。如果为假,则其后的逻辑 &&的第二个操作数不相关。第一个不是真的,所以它不可能是第一个而第二个是真的。
现在,在这种情况下是逻辑的第一边 || 为假,但如果另一方(第三部分)为真,则它可能为真。

所以第三部分会被评估——主要是把消息写成副作用。 (它的结果 0 为真,我们在这里不使用)

其他情况类似,但更简单——而且——我保证!是 - 可以 - 易于阅读! (我没有,但我认为作为一名留着白胡子的 UNIX 资深人士对此有很大帮助。)


... && ... || ... 通常不受欢迎(抱歉,灰胡子的 Unix 资深人士,您一直都错了),因为它在语义上不等同于 if ... then ... else ...。别担心,this is a common pitfall
@gniourf_gniourf OP 没有错——他们也不会像你建议的那样无知。 ... && ... || ... 是一个完全有效的模式和一个常见的 bash 习惯用法。使用它确实规定了先验知识(如果观众中有初学者,请记住这一点),但 OP 有头发证明他们知道如何避免打开井盖。
@ebpa 如果 && 之后的语句返回 false 值怎么办,将继续执行 || 之后的语句?如果是这样,那是错误的,也许这就是 gniourf 的建议
我认为回声只是一个例子。 && 之后的语句可能仍返回非零值
@gniourf_gniourf +1 用于发布 Bash Pitfalls 的链接!很有用!
P
Peter Mortensen

以下脚本逐行读取名为“testonthis”的文件,然后将每一行与一个简单字符串、一个带有特殊字符的字符串和一个正则表达式进行比较。如果不匹配,则脚本将打印该行,否则不打印。

Bash 中的空间非常重要。所以以下将起作用:

[ "$LINE" != "table_name" ] 

但以下不会:

["$LINE" != "table_name"] 

所以请按原样使用:

cat testonthis | while read LINE
do
if [ "$LINE" != "table_name" ] && [ "$LINE" != "--------------------------------" ] && [[ "$LINE" =~ [^[:space:]] ]] && [[ "$LINE" != SQL* ]]; then
echo $LINE
fi
done

使用 this approach 浏览文件。也就是说,删除 UUoC 等。
这并不重要,因为 bash 但因为 [ 实际上是一个外部二进制文件(如在 which [ 中产生类似 /usr/bin/[ 的东西)
P
Peter Mortensen

您还可以使用用例/esac:

case "$string" in
 "$pattern" ) echo "found";;
esac

这是等价的还是包含的?
@ytpillai,这是等效的。请记住,您可以在 ) 之前使用 | 分隔模式。 in 语句相当于 if 语句中的 then。你可能会争辩说它适用于模式列表,如果你来自 Python,每个列表都有自己的声明。不像 substring in string,而是 for item in list。如果您需要 else 条件,请使用 * 作为最后一条语句。它在第一次相遇时返回。
P
Peter Mortensen

Bash 4+ 示例。注意:当单词包含空格等时,不使用引号会导致问题。始终在 Bash、IMO 中引用。

以下是 Bash 4+ 中的一些示例:

示例 1,检查字符串中的“是”(不区分大小写):

    if [[ "${str,,}" == *"yes"* ]] ;then

示例 2,检查字符串中的“是”(不区分大小写):

    if [[ "$(echo "$str" | tr '[:upper:]' '[:lower:]')" == *"yes"* ]] ;then

示例 3,检查字符串中的“是”(区分大小写):

     if [[ "${str}" == *"yes"* ]] ;then

示例 4,检查字符串中的“是”(区分大小写):

     if [[ "${str}" =~ "yes" ]] ;then

示例 5,完全匹配(区分大小写):

     if [[ "${str}" == "yes" ]] ;then

示例 6,完全匹配(不区分大小写):

     if [[ "${str,,}" == "yes" ]] ;then

示例 7,完全匹配:

     if [ "$a" = "$b" ] ;then

享受。


对我来说(mac GNU bash 版本 4.4.12(1)-release x86_64-apple-darwin17.0.0),我必须使用 if [ "$a"="$b" ] 否则它不起作用......等号周围不能有空格
s
steviethecat

如果输入只有几个有效条目,我可能会使用正则表达式匹配。例如,只有“开始”和“停止”是有效的动作。

if [[ "${ACTION,,}" =~ ^(start|stop)$ ]]; then
  echo "valid action"
fi

请注意,我使用双逗号将变量 $ACTION 小写。另请注意,这不适用于过于陈旧的 bash 版本。


P
Peter Mortensen

我这样做的方式与 Bash 和 Dash (sh) 兼容:

testOutput="my test"
pattern="my"

case $testOutput in (*"$pattern"*)
    echo "if there is a match"
    exit 1
    ;;
(*)
   ! echo there is no coincidence!
;;esac

使用前面的 ( 与不使用它有什么区别?
P
Peter Mortensen

你有比较问题吗? (如下图?)

var="true"
if [[ $var == "true" ]]; then
  # It should be working, but it is not...
else
  # It is falling here...
fi

尝试使用 =~ 运算符(正则表达式运算符),它可能会起作用:

var="true"
if [[ $var =~ "true" ]];then
  # Now it works here!!
else
  # No more inequality
fi

您可以链接到 =~ 运算符的(官方)文档吗?请通过 editing (changing) your answer 回复,而不是在评论中(没有“编辑:”、“更新:”或类似内容 - 答案应该看起来好像是今天写的)。