Bash,变量的行包含子字符串



在尝试编写一个健壮的bash方法来检测由多行文本组成的变量是否包含子字符串(可能包含空格(时,我遇到了一些困难。编写了三个函数,我使用BATS框架为它们编写了一些测试。功能及其失败的附带测试包括在下面。

方法一

lines_contain_string() {
local substring="$1"
shift
local lines=("$@")

local found_substring="NOTFOUND"
for i in "${lines[@]}"; do
if [[ $i == *"$substring"* ]]; then
echo "FOUND"
local found_substring="FOUND"
fi
done
if [ "$found_substring" == "NOTFOUND" ]; then
echo "NOTFOUND"
fi
}

测试失败:

EXAMPLE_LINES=$(cat <<-END
First line
second line 
third line 
sometoken
END
)
@test "Substring in first line is found in lines by lines_contain_string." {
contained_substring="First line"

actual_result=$(lines_contain_string "$contained_substring" "${EXAMPLE_LINES}")
#actual_result=$(lines_contain_string_with_space "$contained_substring" "${EXAMPLE_LINES}")
EXPECTED_OUTPUT="FOUND"

assert_equal "$actual_result" "$EXPECTED_OUTPUT"
}

因此,第一个方法不会捕获所有子字符串。

方法二

第二种方法:

lines_contain_string_with_space() {
local substring="$1"
local lines="$@"
if [ "$lines" == "" ]; then
echo "NOTFOUND"
# shellcheck disable=SC2154
elif [[ "$lines" =~ "$substring" ]]; then
echo "FOUND"; 
else
echo "NOTFOUND";
fi
}

这似乎返回假阳性/似乎总是返回"假阳性";FOUND";,例如,在测试中:

EXAMPLE_LINES=$(cat <<-END
First line
second line 
third line 
sometoken
END
)
@test "lines_contain_string returns NOTFOUND on non-existing substring." {
contained_substring="Non-existing-substring"

#actual_result=$(lines_contain_string "$contained_substring" "${EXAMPLE_LINES}")
actual_result=$(lines_contain_string_with_space "$contained_substring" "${EXAMPLE_LINES}")
EXPECTED_OUTPUT="NOTFOUND"

assert_equal "$actual_result" "$EXPECTED_OUTPUT"
}

方法三

此方法由choroba:提供

string_in_lines() {
local substring=$1
shift
local lines=$1
if [[ $lines = *"$substring"* ]] ; then
echo FOUND
else
echo NOTFOUND
fi
}

并称之为测试:

@test "Substring in first line is found in lines by lines_contain_string." {
contained_substring="First line"

read -p "EXAMPLE_LINES=$EXAMPLE_LINES"
#actual_result=$(lines_contain_string "$contained_substring" "${EXAMPLE_LINES}")
#actual_result=$(lines_contain_string_with_space "$contained_substring" "${EXAMPLE_LINES}")
actual_result=$(string_in_lines "$contained_substring" "${EXAMPLE_LINES}")
EXPECTED_OUTPUT="FOUND"

assert_equal "$actual_result" "$EXPECTED_OUTPUT"
}

产生输出:

✗ Substring in first line is found in lines by lines_contain_string.
(from function `assert_equal' in file test/no_server_required/preserves_server/../../libs/bats-assert/src/assert_equal.bash, line 40,
in test file test/no_server_required/preserves_server/test_parsing.bats, line 35)
`assert_equal "$actual_result" "$EXPECTED_OUTPUT"' failed
EXAMPLE_LINES=First line
second line 
third line 
sometoken
-- values do not equal --
expected : FOUND
actual   : NOTFOUND
--

问题

一个人怎么能回应";FOUND"/"NOTFOUND";在bash函数中,基于由多行组成的传入变量是否包含可能包含空格的子字符串?(并进行相应的测试。(

备注

由于我对choroba提供的方法的测试也失败了,我认为这种方法很有可能成功,我预计我的测试函数是不正确的。我相应地更新了这个问题。

choroba的评论建议使用反斜杠:"${EXAMPLE_LINES}";不正确。我测试了一下这是否不正确,结果证明是不正确的。因此,解决方案是将测试写成:

@test "Substring in first line is found in lines by lines_contain_string." {
contained_substring="First line"
#actual_result=$(lines_contain_string "$contained_substring" "${EXAMPLE_LINES}")
#actual_result=$(lines_contain_string_with_space "$contained_substring" "${EXAMPLE_LINES}")
actual_result=$(string_in_lines "$contained_substring" "${EXAMPLE_LINES}")
EXPECTED_OUTPUT="FOUND"

assert_equal "$actual_result" "$EXPECTED_OUTPUT"
}
@test "lines_contain_string returns NOTFOUND on non-existing substring." {
contained_substring="Non-existing-substring"

#actual_result=$(lines_contain_string "$contained_substring" "${EXAMPLE_LINES}")
#actual_result=$(lines_contain_string_with_space "$contained_substring" "${EXAMPLE_LINES}")
actual_result=$(string_in_lines "$contained_substring" "${EXAMPLE_LINES}")
EXPECTED_OUTPUT="NOTFOUND"

assert_equal "$actual_result" "$EXPECTED_OUTPUT"
}

使用带有通配符模式的=

string_in_lines() {
local substring=$1
shift
local lines=$1
if [[ $lines = *"$substring"* ]] ; then
echo FOUND
else
echo NOTFOUND
fi
}

最新更新