Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 验证是否在范围中找到条目_Linux_Shell_Unix_Awk_Command - Fatal编程技术网

Linux 验证是否在范围中找到条目

Linux 验证是否在范围中找到条目,linux,shell,unix,awk,command,Linux,Shell,Unix,Awk,Command,我有两个文件,一个包含单个条目列表(fileA),另一个包含范围列表(fileB) 我想找出fileA中的哪些条目在fileB的任何范围内都可以找到 两个文件中的示例条目都是 fileA 00100500000000 00100600000000 00100700000000 00100800000000 00100900000000 00101000000000 00101300000000 00101500000000 00101600000000 00101700000000 00101

我有两个文件,一个包含单个条目列表(fileA),另一个包含范围列表(fileB)

我想找出fileA中的哪些条目在fileB的任何范围内都可以找到

两个文件中的示例条目都是

fileA

00100500000000
00100600000000
00100700000000
00100800000000
00100900000000
00101000000000 
00101300000000
00101500000000
00101600000000
00101700000000
00101710000000
00101800000000
35014080000000
35014088000000
35067373000000
fileB

00100200000000,00100200999999
00100300000000,00100300999999
00100100000000,00100100999999
00100400000000,00100400999999
00100500000000,00100500999999
00100600000000,00100600999999
00100700000000,00100700999999
00100800000000,00100800999999
00100900000000,00100900999999
00101000000000,00101000999999
00101300000000,00101300999999
00101500000000,00101500999999
00101600000000,00101600999999
35048702000000,35048702999999
35048802000000,35048802999999
35077160000000,35077160999999
35077820000000,35077820999999
35085600000000,35085600999999
我使用了下面的脚本,但在fileA和fileB中分别完成140k和50k个条目大约需要6天。有没有办法让它快得多

list=`cat fileB`
for mobno in $list
do
  LowVal="$(echo $mobno | cut -d, -f1)"
  HighVal="$(echo $mobno | cut -d, -f2)"

 while read ThisLine; 
do [ ${ThisLine} -ge ${LowVal} ] && [ ${ThisLine} -le ${HighVal} ] && echo "${ThisLine}";done < fileA; 
done;
list=`cat fileB`
对于$list中的mobno
做
LowVal=“$(echo$mobno | cut-d,-f1)”
HighVal=“$(echo$mobno | cut-d,-f2)”
一边读这行;
执行[${ThisLine}-ge${LowVal}]&&[${ThisLine}-le${HighVal}]&&echo“${ThisLine}”;完成
两种方法:

--使用grep

grep -of fileA fileB

--使用comm+sort+sed命令:

comm -12 <(sort fileA) <(sed 's/,/\n/' fileB | sort)

如果fileB上的范围像示例中那样递增,那么只需要第一个和最后一个值LowVal和HighVal。试试这个:

LowVal=$(head -n1 fileB | cut -d, -f1)
HighVal=$(tail -n1 fileB | cut -d, -f2)

awk -vHighVal=$HighVal -vLowVal=$LowVal '$0 >= LowVal && $0 <= HighVal' fileA
LowVal=$(头部-n1文件b |切割-d,-f1)
HighVal=$(尾部-n1文件B |切割-d,-f2)

awk-vHighVal=$HighVal-vLowVal=$LowVal'$0>=LowVal&&$0您必须测试它的性能,但以下awk脚本解决方案是一个选项:

NR == 1 && FNR == 1 { strt=1
        }
FNR == 1 && NR != 1 {
        strt=0
        }
strt==0 {
        pos=$0
        for (i in ranges) {
                split(i,arry,",")
                if ( pos >= arry[1] && pos <= arry[2]) {
                        print i" - "$0
                        }
                }
        }
strt==1 {ranges[$0]=""
        }
输出:

00100500000000,00100500999999 - 00100500000000
00100600000000,00100600999999 - 00100600000000
00100700000000,00100700999999 - 00100700000000
00100800000000,00100800999999 - 00100800000000
00100900000000,00100900999999 - 00100900000000
00101000000000,00101000999999 - 00101000000000
00101300000000,00101300999999 - 00101300000000
00101500000000,00101500999999 - 00101500000000
00101600000000,00101600999999 - 00101600000000
00101700000000,00101700999999 - 00101700000000
00101710000000,00101710999999 - 00101710000000
00101800000000,00101800999999 - 00101800000000

我们实际上是在使用变量strt读取两个文件,以确定一个文件的结尾和另一个文件的开头。我们将范围读入一个数组(ranges),然后从范围和fileA中的每个值中删除前导零以进行比较。

Cut似乎很慢,这就是为什么它花费了这么多时间。试试这个代码

list=`cat fileB`
for mobno in $list
do
  IFS=', ' read -r -a array <<< $mobno
  LowVal=${array[0]}
  HighVal=${array[1]}

 while read ThisLine; 
do [ ${ThisLine} -ge ${LowVal} ] && [ ${ThisLine} -le ${HighVal} ] && echo "${ThisLine}";done < fileA; 
done;
list=`cat fileB`
对于$list中的mobno
做

如果s=','read-r-a array这是我的看法<代码>awk
是使用的工具。在这里,它是作为一个班轮:

$ awk -F, 'NR==FNR{range[$1]=$2;next}{for(low in range){if($1>=low&&$1<=range[low]){print $1}}}' fileB fileA
或者,断章取义的脚本样式(带注释)

declare-A范围=()
当IFS=,read-rab;做
范围[“$a”]=“$b”#将范围存储在关联数组中
完成
这里一个比较迟钝的地方是测试值开头的
10 
。之所以出现这些,是因为如果没有它们,bash会将前导为零的整数解释为八进制数,这在数据集中会失败,因为它包含8和9。:-)


更新#2

纯粹出于实验目的,这里有一个可能适用于bash版本3的变体

这仍然使用数组,但使用传统数组而不是关联数组。因此,索引是数字的,因此
$low
的数字比较不再需要基数填充(
1035;

declare-a范围=()
当IFS=,read-rab;做
范围[10#“$a”]=“$b”#将范围存储在关联数组中
完成
文件的每一行之间真的有空行吗?这看起来像是间隔搜索问题。我建议看一下文献中的区间树。该数据结构将提高算法的渐进复杂性。看起来这就是100K’s中的数据集所需要的,另一个选项是对间隔进行两次排序。一次是关于起始值,然后是关于结束值。对于fileA中的每个条目,您需要在这两个已排序的间隔列表中进行两次修改的二进制搜索。fileB的范围是否与您的示例中的相同?嗯,不,他希望从fileA中查找在fileB中列出的范围内的值,而不是寻找精确的匹配。他的样本数据是蹩脚的,这一事实不应混淆这个问题。:-)不幸的是,执行速度仍然是sameI-get-down-errors行1:declare:-A:invalid选项declare:usage:declare[-afFirtx][p][name[=value]…]行4:00100800000000:value对base太大(错误标记为“00100800000000”),正如我在注释中提到的,关联数组需要bash 4。您使用的是什么版本的bash?(
echo$BASH_VERSION
to check。)注意,macOS附带BASH VERSION 3。如果您使用的是macOS,则可以从或安装更新的bash。您正在运行什么操作系统和版本?(你的问题被标记为linux。)啊,可敬的SLES 11。虽然您可以从源代码或未经授权的rpm安装bash,但使用awk解决方案的工作量会减少,而且它可能会执行得更快。也许是时候考虑升级了,这样你可以得到一些更现代的工具。Bash4于2009年发布@Raziel,我添加了一个Bash3选项,在macOS(Bash3.2.57)中似乎对我有效。我很想知道它是否适用于您,以及它与您的数据集的awk选项相比如何。不幸的是,它给出了不期望的结果。请参阅输出的摘录。您似乎只检查了最后12位数字861008000000860080399999-00100800000000 00100800000000000010080099999-00100800000000 0110080000000110080099999-00100800000000我已更改解决方案以处理整个字符串,而不仅仅是最后12位数字。非常感谢。我的问题解决了。处理所有条目需要4小时35分钟。
list=`cat fileB`
for mobno in $list
do
  IFS=', ' read -r -a array <<< $mobno
  LowVal=${array[0]}
  HighVal=${array[1]}

 while read ThisLine; 
do [ ${ThisLine} -ge ${LowVal} ] && [ ${ThisLine} -le ${HighVal} ] && echo "${ThisLine}";done < fileA; 
done;
$ awk -F, 'NR==FNR{range[$1]=$2;next}{for(low in range){if($1>=low&&$1<=range[low]){print $1}}}' fileB fileA
$ awk '

    BEGIN {
      RS=","         # Record separator, "-F," in the one-liner
    }

    NR==FNR {        # Run this bit on just the first file specified, your ranges
      range[$1]=$2   # Store the range in an array
      next
    }

    {                           # For each value in your data file,
      for (low in range) {      # step through the ranges
        if ($1 >= low && $1 <= range[low]) {  # and test.
          print $1              # If they pass, print the value.
        }
      }
    }

  ' fileB fileA
$ declare -A range=()
$ while IFS=, read -r a b; do range["$a"]="$b"; done < fileB
$ while read -r val; do for low in "${!range[@]}"; do [[ 10#$val -ge 10#$low && 10#$val -le 10#${range[$low]} ]] && echo "$val"; done; done < fileA
declare -a range=()

while IFS=, read -r a b; do
  range[10#"$a"]="$b"                      # Store the ranges in an associative array
done < fileB                            # (requires bash 4+)

while read -r val; do                   # Read values...
  for low in "${!range[@]}"; do         # Step through our range, and
    [[ 10#$val -ge 10#$low && 10#$val -le 10#${range[$low]} ]] &&
    echo "$val"                         # test and print.
  done
done < fileA