使用 shell 脚本检查另一个文件中的数字是否在范围内
Check number in another file if in range using shell script
我有两个文件(fileA 和 fileB)。 FileA 包含数字列表,fileB 包含数字范围。
文件A
446646452
000000001
63495980020
fileB(range_from 和 range_to)
22400208, 22400208
446646450, 446646450
63495980000, 63495989999
输出必须是
63495980020
在sql脚本中就像
select *
from fileB
where 446646452 between Range_from and Range_To
如何使用 shell 脚本来完成?
打印匹配任何范围的数字
$ awk 'FNR==NR{low[NR]=+0; hi[NR]=+0;next} {for (i in low)if (>low[i] && <hi[i]){print ;next}}' fileB fileA
63495980020
工作原理
FNR==NR{low[NR]=+0; hi[NR]=+0;next}
读取第一个文件时,fileB
,将范围的低端保存在数组 low
中,将范围的高端保存在数组 hi
.
中
for (i in low)if (>low[i] && <hi[i]){print ;next}
读取第二个文件时,fileA
,检查每个范围内的数字。如果它满足任何范围,则打印它并跳到 next
行。
打印符合各自范围的数字
$ paste fileA fileB | awk '>+0 && <+0{print }'
63495980020
注意只打印了63495980020。 446646452不在22400208和22400208之间,所以省略
工作原理
实用程序 paste
组合文件如下:
$ paste fileA fileB
446646452 22400208, 22400208
000000001 446646450, 446646450
63495980020 63495980000, 63495989999
第一列是我们感兴趣的数字,第二列是范围的低值,第三列是高值。我们要打印第一个值 </code>,如果它介于第二个和第三个之间。要测试它是否大于第二个,我们可以尝试:</p>
<pre><code>>
但是,为了确保 awk
将字段视为数字而不是字符串,我们对其中一个数字执行加法,如下所示:
>+0
同理,判断第一个数是否小于第三个数:
<+0
将这两个测试与打印命令放在一起产生:
>+0 && <+0 {print }
此测试严格介于之间。根据您的要求,您可能更喜欢:
>=+0 && <=+0 {print }
根据 OP 的说明,fileA
中的每个值都应根据 fileB
中的 所有 范围进行检查,以查看它是否属于 至少一个范围。
假定范围检查的 >=
和 <=
逻辑(即包括与范围端点一致的值)。
awk -F', +' '
# 1st pass (fileB): read the lower and upper range bounds
FNR==NR { lbs[++count] = +0; ubs[count] = +0; next }
# 2nd pass (fileA): check each line against all ranges.
{
for(i=1;i<=count;++i) {
if (+0 >= lbs[i] && +0 <= ubs[i]) { print; next }
}
}
' fileB fileA
awk
用于读取两个文件,使用单独的通道:
FNR==NR
对来自 fileB
的所有行都成立;构建范围的下限 (lbs
) 和上限 (ubs
) 的并行数组;感谢 next
,没有对 fileB
行应用进一步处理。
- 随后的
{...}
块仅应用于来自 fileA
. 的行
- 针对所有范围检查
fileA
中的每个值,一旦找到匹配项,就会打印输入行并继续处理下一行。
- 为了确保所有涉及的标记都被视为 数字,
+0
被添加到它们。
老式脚本
sed 's/,[[:space:]]*/ /' fileB \
| while read LowVal HighVal
do
while read ThisLine
do
[ ${ThisLine} -ge ${LowVal} ] && [ ${ThisLine} -le ${HighVal} ] && echo "${ThisLine}"
done < fileA
done
我有两个文件(fileA 和 fileB)。 FileA 包含数字列表,fileB 包含数字范围。
文件A
446646452
000000001
63495980020
fileB(range_from 和 range_to)
22400208, 22400208
446646450, 446646450
63495980000, 63495989999
输出必须是
63495980020
在sql脚本中就像
select *
from fileB
where 446646452 between Range_from and Range_To
如何使用 shell 脚本来完成?
打印匹配任何范围的数字
$ awk 'FNR==NR{low[NR]=+0; hi[NR]=+0;next} {for (i in low)if (>low[i] && <hi[i]){print ;next}}' fileB fileA
63495980020
工作原理
FNR==NR{low[NR]=+0; hi[NR]=+0;next}
读取第一个文件时,
中fileB
,将范围的低端保存在数组low
中,将范围的高端保存在数组hi
.for (i in low)if (>low[i] && <hi[i]){print ;next}
读取第二个文件时,
fileA
,检查每个范围内的数字。如果它满足任何范围,则打印它并跳到next
行。
打印符合各自范围的数字
$ paste fileA fileB | awk '>+0 && <+0{print }'
63495980020
注意只打印了63495980020。 446646452不在22400208和22400208之间,所以省略
工作原理
实用程序 paste
组合文件如下:
$ paste fileA fileB
446646452 22400208, 22400208
000000001 446646450, 446646450
63495980020 63495980000, 63495989999
第一列是我们感兴趣的数字,第二列是范围的低值,第三列是高值。我们要打印第一个值 </code>,如果它介于第二个和第三个之间。要测试它是否大于第二个,我们可以尝试:</p>
<pre><code>>
但是,为了确保 awk
将字段视为数字而不是字符串,我们对其中一个数字执行加法,如下所示:
>+0
同理,判断第一个数是否小于第三个数:
<+0
将这两个测试与打印命令放在一起产生:
>+0 && <+0 {print }
此测试严格介于之间。根据您的要求,您可能更喜欢:
>=+0 && <=+0 {print }
根据 OP 的说明,fileA
中的每个值都应根据 fileB
中的 所有 范围进行检查,以查看它是否属于 至少一个范围。
假定范围检查的 >=
和 <=
逻辑(即包括与范围端点一致的值)。
awk -F', +' '
# 1st pass (fileB): read the lower and upper range bounds
FNR==NR { lbs[++count] = +0; ubs[count] = +0; next }
# 2nd pass (fileA): check each line against all ranges.
{
for(i=1;i<=count;++i) {
if (+0 >= lbs[i] && +0 <= ubs[i]) { print; next }
}
}
' fileB fileA
awk
用于读取两个文件,使用单独的通道:FNR==NR
对来自fileB
的所有行都成立;构建范围的下限 (lbs
) 和上限 (ubs
) 的并行数组;感谢next
,没有对fileB
行应用进一步处理。- 随后的
{...}
块仅应用于来自fileA
. 的行
- 针对所有范围检查
fileA
中的每个值,一旦找到匹配项,就会打印输入行并继续处理下一行。 - 为了确保所有涉及的标记都被视为 数字,
+0
被添加到它们。
老式脚本
sed 's/,[[:space:]]*/ /' fileB \
| while read LowVal HighVal
do
while read ThisLine
do
[ ${ThisLine} -ge ${LowVal} ] && [ ${ThisLine} -le ${HighVal} ] && echo "${ThisLine}"
done < fileA
done