【问题标题】:Replace array iteration with regex用正则表达式替换数组迭代
【发布时间】:2014-08-31 23:41:12
【问题描述】:

我想在两个数组中找到部分匹配的 ipv6 前缀。例如,一个数组中的2001:db8: 将匹配另一个数组中的2001:db8:1::/482001:db8:2::/48

我已经通过迭代另一个数组来让它工作:

ru_routes=( $(curl -4 ftp://ftp.ripe.net/ripe/stats/delegated-ripencc-latest | egrep -o '\|RU\|ipv6\|.+?::\|[0-9]+' | cut -d'|' -f4 | sed 's/::$/:/g') );
msk_ix_routes=( $(curl -4 http://www.msk-ix.ru/download/lg/msk_ipv6_pfx.txt.gz | gunzip | egrep -o '\b.*::/[0-9]*') );
routes=();
for item1 in ${msk_ix_routes[@]}; do
    for item2 in ${ru_routes[@]}; do
        if [[ $item1 = $item2* ]]; then
            routes+=( $item1 );
            break
        fi
    done
done

但它在我的 mips 路由器上运行有点慢(约 90 秒)。我找到了this useful answer,它运行得更快,但我无法让它以与上述相同的方式工作。而且我认为我不需要像示例中那样的“if”构造,因为它会两次做同样的事情。我的不工作版本:

msk=" ${msk_ix_routes[*]} ";         # add framing blanks

for item in ${ru_routes[@]}; do
  routes+=( egrep -o "$item[\S]*/g" <<< $msk );
done

我猜这里引用和转义有问题,但我无法解决。请帮忙)我愿意接受建议。

顺便说一句,我在第一个版本中使用了“comm”,它运行得更快,但后来它只完全匹配,因此我开始玩循环:

routes=( $(comm -12 <(printf '%s\n' "${ru_routes[@]}" | LC_ALL=C sort) <(printf '%s\n' "${msk_ix_routes[@]}" | LC_ALL=C sort)) );

【问题讨论】:

  • 与您要引用 [@] 列表扩展以防止数组元素分词的任何其他内容无关(在您的情况下可能不是问题,但通常是正确的做事方式)。
  • 那两个不起作用的选项不起作用怎么办?他们在做什么? (第二个看起来将创建一个空列表,因为 [[ 测试不返回任何内容(仅返回代码)。您几乎肯定希望在 if 块中进行该测试,然后附加 @987654331 @ 到列表中(就像在链接的问题中一样)。
  • 我同意第二个选项(删除它)第一个给我 889111 匹配而不是 4xx 有效匹配。 $item 将是一个完全匹配,我想获得所有更长的匹配(子字符串)

标签: regex bash debian-based


【解决方案1】:

Bash 脚本的效率一点也不高。试试这个:

#!/bin/bash

# e. g.: ripencc|RU|ipv6|2001:640::|32|19991115|allocated -> ^2001:640:
awk -v FS='|' \
    '$2 == "RU" && $3 == "ipv6" { sub(/::/, ":", $4); print "^" $4 }' \
    <(curl -4 ftp://ftp.ripe.net/ripe/stats/delegated-ripencc-latest) \
|\
# grep e. g. '^2001:640:' in '2001:640:8000::/33'
grep --basic-regexp --file - \
    <(curl -4 http://www.msk-ix.ru/download/lg/msk_ipv6_pfx.txt.gz | gunzip)

【讨论】:

  • 感谢 Dmitry 同志,您的最后一次编辑成功了。它比循环快得多。任何方式一起删除来自 msk_ipv6_pfx.txt 的重复记录?例如 2a02:bc8::/32 和 2a02:bc8:fffe::/48。两条路线都将前往 IX,但更高的前缀就足够了(2a02:bc8::/32 已授权)。再次感谢您
  • @X 不客气。 :-) 至于删除msk_ipv6_pfx.txt 中的重复条目,它看起来并不简单,可以作为一个单独的问题,实际上在这里,关于 SO。但是,是的,当然,这是可能的。例如:$ tac msk_ipv6_pfx.txt | awk -F '::' -v P='^$' '!/^[# ]/ &amp;&amp; $0 != "" &amp;&amp; $1 !~ P { P = "^" $1; print }'。不过,这不是一种最佳方式——它可以在不反转文件的情况下完成。你需要什么cmets吗?
  • 我确实看到行数减少了,但上面提到的两个前缀仍然存在(无论如何都需要在它上面过夜)。但我真的很感激在 curl 和 gunzip 之后重定向以使用 msk-ix 文件提供 grep 的提示。否则我想必须将它定义为一个单独的变量。谢谢
  • @Xand 至于curl,如果临时文件不适合 - 请参阅编辑后的答案。
  • @Xand 至于删除msk_ipv6_pfx.txt 的冗余,好吧,我没注意——实际上tac 还不够,我们重新整理了一个文件:$ sort -n msk_ipv6_pfx.txt | awk -F '::' -v P='^$' '!/^[# ]/ &amp;&amp; $0 != "" &amp;&amp; $1 !~ P { P = "^" $1; print }'
猜你喜欢
  • 2015-06-25
  • 2019-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-24
  • 2015-07-25
  • 2012-08-01
相关资源
最近更新 更多