在文件中搜索子字符串匹配 bash
Search for substring matches in a file bash
前提是要存储一个由冒号分隔的值代表项目的数据库文件。
var1:var2:var3:var4
我需要对该文件进行排序并提取任何值与搜索字符串匹配的行。
例如
Search for "Help"
Hey:There:You:Friends
I:Kinda:Need:Help (this line would be extracted)
我正在使用一个函数来传递搜索字符串,然后将找到的行传递给另一个函数来格式化输出。但是,我似乎无法在通过时获得正确的格式。这是我尝试过的示例代码,我在这个网站上找到了不同的方法,但它们似乎对我不起作用
#Option 1, it doesn't ever find matches
function retrieveMatch {
if [ -n "" ]; then
while read line; do
if [[ *""* =~ "$line" ]]; then
formatPrint "$line"
fi
done
fi
}
#Option 2, it gets all the matches, but then passes the value in a
#format different than a file? At least it seems to...
function retrieveMatch {
if [ -n "" ]; then
formatPrint `cat database.txt | grep ""`
fi
}
function formatPrint {
list="database.txt" #default file for printing all info
if [ -n "" ]; then
list=""
fi
IFS=':'
while read var1 var2 var3 var4; do
echo "$var1"
echo "$var2"
echo "$var3"
echo "$var4"
done < "$list"
}
我似乎无法让第一个找到任何匹配项
第二个选项获得了正确的值,但是当我尝试格式化打印时,它抛出一个错误,指出传入的值列表不是目录。
我觉得我一定错过了什么,但是..
cat > foo.txt
Hey:There:You:Friends I:Kinda:Need:Help
Foo:Bar
[控制-D]
grep -i help foo.txt
Hey:There:You:Friends I:Kinda:Need:Help
符合要求吗?
编辑:进一步扩展这个想法..
cat > foo.bsh
#!/bin/bash
hits="$(grep -i help foo.txt)"
while read -r line; do
echo "${line}"
done <<< "$hits"
[控制-D]
老实说,我会将整个内容替换为
function retrieveMatch {
grep "" | tr ':' '\n'
}
被称为
retrieveMatch Help < filename
...像原来的功能(选项1)似乎是设计出来的。要用匹配行做更复杂的事情,看看 awk:
# in the awk script, the fields in the line will be , etc.
awk -v pattern="" -F : '[=12=] ~ pattern { for(i = 1; i < NF; ++i) print $i }'
参见 this link。 awk 就是用来处理这类数据的,所以如果你打算用它做复杂的事情,它绝对值得一看。
更直接地回答问题,您的代码中存在 two/three 个问题。一个是,正如在对该问题的评论中指出的那样,
行
if [[ *""* =~ "$line" ]]; then
将尝试使用 "$line"
作为正则表达式在 *""*
中查找匹配项,假设 *""*
在路径名扩展后不会变成多个标记,因为 *
没有被引用。假设 *
应该按照它们在 glob 表达式中的方式匹配任何内容(但不是在正则表达式中),这可以替换为
if [[ "$line" =~ "" ]]; then
因为如果正则表达式匹配字符串的任何部分,=~
将报告匹配。
第二个问题是您在 formatPrint
中的 "$list"
是一个文件还是一行的问题上存在分歧。你在retrieveMatch
中说应该是一行:
formatPrint "$line"
但是你在formatPrint
中将其设置为默认文件名:
list="database.txt" #default file for printing all info
你必须决定一个。如果您决定 formatPrint
应该格式化行,那么第三个问题是
中的重定向
while read var1 var2 var3 var4; do
echo "$var1"
echo "$var2"
echo "$var3"
echo "$var4"
done < "$list"
尝试使用 "$list"
作为文件名。这可以通过将最后一行替换为
来解决
done <<< "$list" # using a here-string (bash-specific)
或者
done <<EOF
$list
EOF
(注意:在后一种情况下,不要缩进代码;它是逐字记录的此处文档)。当然,read
只会按照您编写的方式拆分四个字段。
前提是要存储一个由冒号分隔的值代表项目的数据库文件。
var1:var2:var3:var4
我需要对该文件进行排序并提取任何值与搜索字符串匹配的行。 例如
Search for "Help"
Hey:There:You:Friends
I:Kinda:Need:Help (this line would be extracted)
我正在使用一个函数来传递搜索字符串,然后将找到的行传递给另一个函数来格式化输出。但是,我似乎无法在通过时获得正确的格式。这是我尝试过的示例代码,我在这个网站上找到了不同的方法,但它们似乎对我不起作用
#Option 1, it doesn't ever find matches
function retrieveMatch {
if [ -n "" ]; then
while read line; do
if [[ *""* =~ "$line" ]]; then
formatPrint "$line"
fi
done
fi
}
#Option 2, it gets all the matches, but then passes the value in a
#format different than a file? At least it seems to...
function retrieveMatch {
if [ -n "" ]; then
formatPrint `cat database.txt | grep ""`
fi
}
function formatPrint {
list="database.txt" #default file for printing all info
if [ -n "" ]; then
list=""
fi
IFS=':'
while read var1 var2 var3 var4; do
echo "$var1"
echo "$var2"
echo "$var3"
echo "$var4"
done < "$list"
}
我似乎无法让第一个找到任何匹配项 第二个选项获得了正确的值,但是当我尝试格式化打印时,它抛出一个错误,指出传入的值列表不是目录。
我觉得我一定错过了什么,但是..
cat > foo.txt
Hey:There:You:Friends I:Kinda:Need:Help
Foo:Bar
[控制-D]
grep -i help foo.txt
Hey:There:You:Friends I:Kinda:Need:Help
符合要求吗?
编辑:进一步扩展这个想法..
cat > foo.bsh
#!/bin/bash
hits="$(grep -i help foo.txt)"
while read -r line; do
echo "${line}"
done <<< "$hits"
[控制-D]
老实说,我会将整个内容替换为
function retrieveMatch {
grep "" | tr ':' '\n'
}
被称为
retrieveMatch Help < filename
...像原来的功能(选项1)似乎是设计出来的。要用匹配行做更复杂的事情,看看 awk:
# in the awk script, the fields in the line will be , etc.
awk -v pattern="" -F : '[=12=] ~ pattern { for(i = 1; i < NF; ++i) print $i }'
参见 this link。 awk 就是用来处理这类数据的,所以如果你打算用它做复杂的事情,它绝对值得一看。
更直接地回答问题,您的代码中存在 two/three 个问题。一个是,正如在对该问题的评论中指出的那样,
行if [[ *""* =~ "$line" ]]; then
将尝试使用 "$line"
作为正则表达式在 *""*
中查找匹配项,假设 *""*
在路径名扩展后不会变成多个标记,因为 *
没有被引用。假设 *
应该按照它们在 glob 表达式中的方式匹配任何内容(但不是在正则表达式中),这可以替换为
if [[ "$line" =~ "" ]]; then
因为如果正则表达式匹配字符串的任何部分,=~
将报告匹配。
第二个问题是您在 formatPrint
中的 "$list"
是一个文件还是一行的问题上存在分歧。你在retrieveMatch
中说应该是一行:
formatPrint "$line"
但是你在formatPrint
中将其设置为默认文件名:
list="database.txt" #default file for printing all info
你必须决定一个。如果您决定 formatPrint
应该格式化行,那么第三个问题是
while read var1 var2 var3 var4; do
echo "$var1"
echo "$var2"
echo "$var3"
echo "$var4"
done < "$list"
尝试使用 "$list"
作为文件名。这可以通过将最后一行替换为
done <<< "$list" # using a here-string (bash-specific)
或者
done <<EOF
$list
EOF
(注意:在后一种情况下,不要缩进代码;它是逐字记录的此处文档)。当然,read
只会按照您编写的方式拆分四个字段。