在文件bash中搜索子字符串匹配

时间:2015-01-29 22:04:57

标签: regex 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 "$1" ]; then
    while read line; do
      if [[ *"$1"* =~ "$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 "$1" ]; then
    formatPrint `cat database.txt | grep "$1"`
  fi
}

function formatPrint {
  list="database.txt" #default file for printing all info
  if [ -n "$1" ]; then
    list="$1"
  fi
  IFS=':'
  while read var1 var2 var3 var4; do
    echo "$var1"
    echo "$var2"
    echo "$var3"
    echo "$var4"
  done < "$list"
}

我似乎无法找到第一个找到任何匹配的人 第二个选项获取正确的值,但是当我尝试formatPrint时,它会抛出一个错误,指出传入的值列表不是目录。

2 个答案:

答案 0 :(得分:2)

老实说,我用

替换整个事情
function retrieveMatch {
  grep "$1" | tr ':' '\n'
}

被称为

retrieveMatch Help < filename

...像原始功能(选项1)似乎是设计的。要使用匹配的行做更复杂的事情,请查看awk:

# in the awk script, the fields in the line will be $1, $2 etc.
awk -v pattern="$1" -F : '$0 ~ pattern { for(i = 1; i < NF; ++i) print $i }'

this link。 awk用于处理这类数据,所以如果你打算用它做复杂的事情,那绝对值得一看。

更直接地回答问题,代码中有两个/三个问题。正如在对问题的评论中指出的那样,一行是

if [[ *"$1"* =~ "$line" ]]; then

将尝试使用"$line"作为正则表达式在*"$1"*中查找匹配项,假设*"$1"*在路径名扩展后不会成为多个令牌,因为{{1}没有引用。假设*应该按照它们在glob表达式中的方式匹配(但不能在正则表达式中),这可以用

替换
*

因为如果正则表达式匹配字符串的任何部分,if [[ "$line" =~ "$1" ]]; then 将报告匹配。

第二个问题是,您是否希望=~中的"$list"成为文件或行。你在formatPrint说它应该是一行:

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 只会按照您编写的方式拆分四个字段。

答案 1 :(得分:1)

我觉得我必须遗漏一些东西,但是......

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]