我有一个变量,其中包含例如['Cars', 'House', 'Bike']
。我希望能够搜索与字符串中包含的值的完全匹配。
示例:
Cars
。它应该返回true
。Car
。它应该返回false
。我尝试过的:
#!/bin/bash
search="Car"
arr="['Cars', 'House', 'Bike']"
if [[ $search =~ .*"$arr".* ]]; then
echo "true"
else
echo "false"
fi
# Output true | Expected false
另一个脚本:
#!/bin/bash
search="Cars"
arr="['Cars', 'House', 'Bike']"
check=0
grep -o "'[^']*'" <<<"$arr" | sed "s/'//g" |
while read -r elem; do
if [ "$search" == "$elem" ]; then
check=1
fi
done
if [ "$check" == 1 ]; then
echo "true"
else
echo "false"
fi
# Output false | Expected true
答案 0 :(得分:1)
在Python中:
search="Car"
arr="['Cars', 'House', 'Bike']"
import ast
output = search in ast.literal_eval(arr)
作为输出True
或False
的shell脚本中的单行代码:
python -c 'import sys; import ast; print(sys.argv[1] in ast.literal_eval(sys.argv[2]))' "$search" "$arr"
作为shell脚本中的单行代码,返回0(正常)或-1(不正常)退出状态,就像在shell中一样:
python -c 'import sys; import ast; sys.exit(0 if sys.argv[1] in ast.literal_eval(sys.argv[2]) else -1)' "$search" "$arr"
答案 1 :(得分:1)
正如其他人所说,使用jq
来解析bash中的JSON。
如果您真的不想这么做,可以尝试以下任何一种方法:
search="'Car'" # add the single quotes to the search string
# or
search="\bCar\b" # \b is regex syntax for word boundary, meaning the word begins/ends there
答案 2 :(得分:1)
有关使用其他某种语言执行此操作的一些答案。我想您想知道为什么您的bash脚本无法正常工作。
从根本上讲,原因是当您在if语句中设置check=1
时,您所处的外壳不同,因此它不会影响外部脚本中定义的check
。这是一个不同的shell,因为您正在将输入从另一个命令传递到while中。
几种可行的方法:
将grep
管道的输出发送到一个临时文件,然后在主shell脚本中执行while循环并从文件中读取输入。
您还可以通过退出代码返回是否找到了您要查找的字符串,并使用存储上一个进程的退出代码的check
变量将其保存在$?
中。
grep -o "'[^']*'" <<<"$arr" | sed "s/'//g" |
while read -r elem; do
if [ "$search" = "$elem" ]; then
exit 1
fi
done
check=$?
由于在while循环中使用退出代码基本上会使它成为fgrep
的较差版本,因此您可以只使用fgrep
并检查退出代码。
答案 3 :(得分:1)
问题的第一个Bash示例代码中的正则表达式匹配存在多个问题。最大的问题是$search
和$arr
在match运算符的错误一侧。模式中缺少(双引号)单引号也是一个严重的问题。无论如何,正则表达式匹配是过大的。简单的“全局”模式匹配就足够了。试试这个:
#!/bin/bash
search=Car
arr="['Cars', 'House', 'Bike']"
if [[ $arr == *"'$search'"* ]]; then
echo true
else
echo false
fi
有关全局模式的信息,请参见glob - Greg's Wiki。
答案 4 :(得分:0)
我找到了一种在循环中修改全局变量的方法。谢谢大家的建议。 这是脚本:
#!/bin/bash
search="Cars"
arr="['Cars', 'House', 'Bike']"
check=0
for elem in $(grep -o "'[^']*'" <<<"$arr" | sed "s/'//g")
do
if [ "$search" == "$elem" ]; then
check=1
fi
done
if [ "$check" == 1 ]; then
echo "true"
else
echo "false"
fi
# Output true | Expected true
答案 5 :(得分:0)
使用红宝石单线:
$ json_arr="['Cars', 'House', 'Bike']"
$ ruby -rjson -e '
data = JSON.parse(ARGV.shift)
puts data.include?(ARGV.shift)
' "${json_arr//\'/\"}" Cars
true
$ ruby -rjson -e '
data = JSON.parse(ARGV.shift)
puts data.include?(ARGV.shift)
' "${json_arr//\'/\"}" Donkey
false
请注意,JSON字符串必须使用双引号(https://json.org/),因此我正在使用Shell的参数替换将单引号转换为双引号。
答案 6 :(得分:0)
如果您除了bash之外不想使用其他任何东西,可以使用bash数组。
一如既往,各有利弊。
优点之一是您无需安装任何其他程序即可使其运行,并且它也可以在其他cygwin
这样的shell中运行。
例如,我写了一段代码:
#!/bin/bash
search="Car"
arr="['Cars', 'House', 'Bike']"
arr="$(printf "%s" "${arr}" | sed -e "s/,//g" -e "s/^\[/(/" -e "s/\]$/)/")"
eval arr="${arr}"
for var in ${arr[@]}; do
if [ "${var}" = "${search}" ]; then
printf "%s\n" "true"
exit
fi
done
printf "%s\n" "false"
无论如何,这段代码都是理所当然的,并且存在一些弊端。
例如,理所当然的是,您的所有输入都像样本,实际变量中没有任何“,”。