我有一个名为my.txt
:
abc_default_flow
#abc_default_flow -p sam
abc_default_flow -p sam
# abc_default_flow -p david
abc_default_flow -p david -z what_is_it
我想匹配包含多个字符串的特定行,并想匹配包含所有字符串的确切行。
我尝试了下面的代码,但是只要它匹配部分字符串,它就会退出循环,而不是包含所有字符串的实际行。
#!/bin/bash -f
f_name=abc_default_flow
p_name=sam
file_content=./my.txt
#echo "file_content: $file_content"
while IFS= read -r file_line
do
echo $file_line
if [[ $file_line != *"#"* ]] && [[ $file_line != "" ]] && echo $file_line | grep -E "${f_name}|${p_name}"; then
#if [[ $file_line != *"#"* ]] && [[ $file_line != "" ]] && echo $file_line | grep -v "${f_name}|${p_name}"; then
#if [[ $file_line != *"#"* ]] && [[ $file_line != "" ]] && [[ $file_line =~ $f_name ]] && [[ $file_line =~ $p_name ]]; then
if [[ -z "$p_name" ]]; then
f_name=${f_name}_${p_name}
fi
echo "f_name: ${f_name}"
break
fi
done < $file_content
使用grep或其他进程在文件中找到正确的行,正确的方法是什么?
更新:使用下面的代码,我能够获得输出,但是是否有任何简单的方法使用grep或sed或awk在单行中找到结果,而不是嵌套的if循环。
#!/bin/bash -f
f_name=abc_default_flow
p_name=david
file_content=./my.txt
echo "f_name: $f_name, p_name: $p_name"
while IFS= read -r file_line
do
if [[ $file_line != *"#"* ]] && [[ $file_line != "" ]]; then
echo "l1"
if [[ ! -z "$f_name" ]] && [[ $file_line =~ "$f_name" ]]; then
echo "l2, $file_line, $f_name, $p_name"
if [[ ! -z "$p_name" ]] && [[ $file_line =~ "$p_name" ]]; then
f_name=${f_name}_${p_name}
echo "f_name: ${f_name}"
break
elif [[ ! -z "$p_name" ]] && [[ ! $file_line =~ "$p_name" ]]; then
continue
else
break
fi
fi
fi
done < $file_content
您可以使用相同的[[ ]]
风格检查您正在寻找的两个字符串:
if [[ $file_line != *"#"* ]] && [[ $file_line == *"$f_name"* ]] && [[ $file_line == *"$p_name"* ]]; then
...
fi
我删除了空字符串检查,因为空行无论如何都不会包含$f_name
和$p_name
。
如果您期望sam
总是在abc_default_flow
之后,那么您可以将两个检查合并为一个测试:
if [[ $file_line != *"#"* ]] && [[ $file_line == *"$f_name"*"$p_name"* ]]; then
...
fi
如果我们将脚本作为一个整体来看,最好不要使用显式逐行循环。当脚本将处理整个文件的工具链接在一起时,脚本更为惯用。比如:
sed -r '/^s*#/d' my.txt | grep "$f_name" | grep "$p_name"