从文件循环正则表达式

时间:2014-01-02 11:41:04

标签: regex arrays bash loops while-loop

谁能看到我在这里做错了什么?这是一个相当复杂的过程,所以让我花一点时间拼出来。我有一个名为“databases”的目录。在该目录中有几个文件,例如“lan.db”,“wan.db”等。下面的脚本首先获取它在databases目录中找到的每个文件,并将文件名放入一个数组中。然后该脚本打开每个单独的文件并逐行读取(忽略注释掉的行)。对于这个问题,我正在使用IP数据库。该脚本打开例如lan.db并逐行读取。每行(较少注释掉的行)包含一个IPv4地址和一个由|分隔的IPv6地址。然后,该脚本将其读取的行与正则表达式进行比较以验证地址。 (注意,这只是一个简单的IPv4正则表达式声明。是的999.999.999.999在技术上是无效的。虽然这个问题不相关)。出于某种原因,脚本没有进行正则表达式比较。我在这里做错了什么?

shopt -s nullglob
DBARRAY=(databases/*)
local i
for i in "${!DBARRAY[@]}"; do
  cat ${DBARRAY[$i]} | grep -v \# | while read LINE; do 
    local IPV4="^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}+\|"
    local IPV6="[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}$"
    DBREGEX="$IPV4$IPV6"
    if [[ ( $LINE =~ $DBREGEX ) ]]; then echo "FAIL"; fi 
  done
done

我知道你会问,“你为什么要拆分正则表达式?”这只是整个正则表达式的一部分。这是检查|分隔文件,我只是想将正则表达式的每个部分放在自己的行上,这样它在编辑时就适合屏幕,因此更容易阅读和修改每个部分。

我在我的剧本的其他地方做过类似的工作,效果很好。我无法弄清楚我在这里编码的错误。谢谢你的帮助!

*更新*

彼得指出了下面的一些事情。因此我稍微更新了代码,因此更有意义。

shopt -s nullglob
DBARRAY=(databases/*)
i=0
for i in "${!DBARRAY[@]}"; do
  cat ${DBARRAY[$i]} | grep -v \# | while read LINE; do 
    IPV4="^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}+\|"
    IPV6="[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}$"
    DBREGEX="$IPV4$IPV6"
    if [[ ( $LINE =~ $DBREGEX ) ]]; then echo "CHEESE"; fi 
  done
done

*更新*

好的,所以我可能终于发现了这种脱节......然而它没有任何意义。在我尝试解释之前让我再次发布代码,但这次有一些小的改动。我已经修剪它以突出问题区域。我还必须添加一些你最初没有看到的真实代码,以使其有任何意义。

Comment Out shopt -s nullglob
Comment Out DBARRAY=(databases/*)
Comment Out i=0
Comment Out   for i in "${!DBARRAY[@]}"; do
Comment Out     cat ${DBARRAY[$i]} | grep -v \# | while read LINE; do 

                IPV4="^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\|"
                IPV6="[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}$"
                DBREGEX="$IPV4$IPV6"
                LINE="1.1.1.1|f:f:f:f:f:f:f:f"
                if [[ !( $LINE =~ $DBREGEX ) ]]; then RETURN="fail" && ERROR="This is the error message that gets reported back!"; return; fi 

Comment Out   done
Comment Out done

注意这个版本我已​​经注释掉了所有的循环,我们正在“模拟”数据库中的一行。在上面的示例中,从数据库模拟的行是有效的。这将是一个无效的例子:LINE =“XXXXXXXX1.1.1.1 | f:f:f:f:f:f:f:f”

现在我们假设我们将上面的错误示例放在数据库中并取消注释while循环,它突然失败了......但是!等待!首先是一些代码:(仅供参考,请注意我是如何静态添加文件位置的,因为第一个循环仍被注释掉)

Comment Out shopt -s nullglob
Comment Out DBARRAY=(databases/*)
Comment Out i=0
Comment Out   for i in "${!DBARRAY[@]}"; do
                cat databases/lan.db | grep -v \# | while read LINE; do 

                IPV4="^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\|"
                IPV6="[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}\:[0-9a-fA-F]{1,4}$"
                DBREGEX="$IPV4$IPV6"
                if [[ !( $LINE =~ $DBREGEX ) ]]; then RETURN="fail" && ERROR="This is the error message that gets reported back!"; return; fi 

              done
Comment Out done

这是非常奇怪的部分。如果我回显$ LINE,它会正确地从数据库中获取它,但显然是比较失败了。因此,即使$ LINE设置正确,它仍然似乎无法在IF语句中进行比较。至少那是看起来正在发生的事情。这有点奇怪吗?或者只是我?

1 个答案:

答案 0 :(得分:0)

您使用错误的正则表达式语法“OR”。使用"|"代替"\|"

示例:

$ [[ abc =~ (abc|def) ]] && echo match || echo nomatch
match
$ [[ abef =~ (abc|def) ]] && echo match || echo nomatch
nomatch
$ [[ def =~ (abc|def) ]] && echo match || echo nomatch
match
$ [[ def =~ (abc\|def) ]] && echo match || echo nomatch
nomatch
$ [[ abc =~ (abc\|def) ]] && echo match || echo nomatch
nomatch