Shell,使用通配符比较两个脚本

yk9xbfzb  于 2023-01-13  发布在  Shell
关注(0)|答案(2)|浏览(115)

我试图在shell脚本中比较两个“几乎”相同的字符串。除了一个字符(A-Z)之外,它们都很相似。在下面的示例中,我希望代码对字符串从1-2-3-A-5-6-1-2-3-Z-5-6-的所有大小写都返回true
目前我的代码返回false。

#!/bin/bash
TEMPLATE='1-2-3-*-5-6-'
CASE='1-2-3-A-5-6-'
if [[ "$TEMPLATE" == "$CASE" ]]; then
  echo "It's there."
else
  echo "NO, improve!"
fi
b4wnujal

b4wnujal1#

模式1-2-3-*-5-6-是一个 glob
这种模式语言在bash手册的Pattern Matching部分中有描述,并且可用于您尝试使用的[[ == ]]测试(下面引用的手册)和注解中提到的case版本。
表情
...使用==!=运算符时,运算符右侧的字符串被视为模式,并根据下面模式匹配下描述的规则进行匹配,就像启用了extglob shell选项一样。=运算符等效于==。如果启用了nocase‐ match shell选项,执行匹配而不考虑字母字符的大小写。
...模式的任何部分都可以用括起来,以强制括起来的部分作为字符串进行匹配。
只有两个约束条件:
1.如果希望模式作为模式而不是文本字符串进行匹配,则不能用引号将其括起来
(see最后引用的段落)
1.图案必须位于操作员的右手侧
(第一段)
所以你的代码可以正常工作

#!/bin/bash
TEMPLATE='1-2-3-*-5-6-'
CASE='1-2-3-A-5-6-'
if [[ $CASE == $TEMPLATE ]]; then
  echo "It's there."
else
  echo "NO, improve!"
fi

注意:使用内置的[[ ]]条件而不是旧的[ ]条件的部分原因是
不对[[]];之间的字执行字拆分和路径名扩展
所以通常不需要给变量加引号(在这个特定的例子中,* 不能 * 至少给其中一个变量加引号)。

uurv41yg

uurv41yg2#

就像这样。

#!/usr/bin/env bash

TEMPLATE='1-2-3-*-5-6-'
CASE='1-2-3-A-5-6-'
if [[ "$CASE" == ${TEMPLATE/\*/[A-Z]} ]]; then
  echo "It's there."
else
  echo "NO, improve!"
fi

或者,您可以直接在赋值语句中添加glob/pattern [A-Z],而不是glob *

#!/usr/bin/env bash

TEMPLATE='1-2-3-[A-Z]-5-6-'
CASE='1-2-3-E-5-6-'
if [[ "$CASE" == $TEMPLATE ]]; then
  echo "It's there."
else
  echo "NO, improve!"
fi

接受的答案已经解释了OP代码的直接错误/问题。只是想添加set -x中的一小段代码,以支持为什么您不需要引用===的rhs Right Hand Side(如果目的是进行模式匹配)。

+ TEMPLATE='1-2-3-[A-Z]-5-6-'
+ CASE=1-2-3-T-5-6-
+ [[ 1-2-3-T-5-6- == \1\-\2\-\3\-\[\A\-\Z\]\-\5\-\6\- ]]
+ echo 'NO, improve!'
NO, improve!

引用===甚至=~操作符的RHS将使它成为一个文本字符串而不是模式/glob/regex,因为每个字符串都有一个前导\,而\是引用/转义shell的一种形式。

相关问题