我从现有程序获取输入,该程序由用管道(|
)字符分隔的字符串组成:
$ echo "$list_of_nodes"
NODE-BB-4|NODE-AA-1|DUMMY
现在我需要检查它们是否存在于单独的文件中:
$ cat file
NODE-BB-4 1.1.1.1
NODE-AA-1 2.2.2.2
情况下-1
应该在输入字符串为"NODE-BB-4|NODE-AA-1"
时传递,因为它们都存在于文件中,
情况下-2
当输入字符串为"NODE-BB-4|NODE-AA-1|DUMMY"
时,如果文件中不存在"DUMMY"
,则应该失败。
这就是我想到这样做但看起来绝对不是最好的主意:
$ echo "$list_of_nodes" |tr '|' '\n' |while read line;
> do grep -q "$line" foo ;
> echo $? ;
> done|awk '{s=s+$0} END{print s}' |awk '$1>0{print "Fail"}'
Fail
这里我循环使用每个模式grep并存储返回代码,然后检查它是否为grater,然后是0。
答案 0 :(得分:2)
这是检查的功能
check() {
FileToCheck="$1"
#cycle will check all patterns.
#if one of patterns will fail, function will stop immediately with Return Code 1
while read p; do
grep "${p}" ${FileToCheck} >/dev/null || { echo "${p} not found in ${FileToCheck}"; return 1; }
done < <( tr '|' '\n' ) #modify input for cycle via tr(replace | by newlines)
#if we running here, all checks are Okay, Return Code 0.
return 0
}
示例文件:
$ cat patterns
NODE-BB-4|NODE-AA-1|DUMMY
$ cat file
NODE-BB-4 1.1.1.1
NODE-AA-1 2.2.2.2
以下是使用的示例:
cat patterns | check file
echo $?
结果:
DUMMY not found in file
1
答案 1 :(得分:1)
Awk
解决方案:
list_of_nodes="NODE-BB-4|NODE-AA-1|DUMMY"
awk -v nodes_str="$list_of_nodes" \
'BEGIN{ len = split(nodes_str, arr, "|") }{ nodes[$1] }
END{ for (i=1; i<=len; i++) if (!(arr[i] in nodes)) print "Fail" }' file
答案 2 :(得分:1)
#!/bin/bash
file="$1"
p="NODE-BB-4|NODE-AA-1|DUMMY"
patterns=${p//|/ }
fileMatchesAllNames () {
file=$1
if [[ $# -eq 1 ]]
then
echo "$file"
else
shift
pattern=$1
shift
grep -q "$pattern" "$file" && fileMatchesAllNames "$file" $@
fi
}
test -f "$file" && fileMatchesAllNames "$file" $patterns
调用该函数时要使用一组模式进行搜索,只需要一个模式进行搜索,然后对其进行测试并使用shift
将其删除以进行下一次调用。
grep -q
就会急切地回来(暗示-m1)。
如果文件与所有模式匹配,则打印其名称。否则,只要模式无法匹配,程序就会静默终止。
它从以前的解决方案修改为SO问题,其中应该检查文件列表并且可以缩短一点,因为文件名不需要一次又一次地传递给函数。
#!/斌/庆典
file="$1"
p="NODE-BB-4|NODE-AA-1|DUMMY"
patterns=${p//|/ }
fileMatchesAllNames () {
if [[ $# -eq 0 ]]
then
echo "$file"
else
pattern=$1
shift
grep -q "$pattern" "$file" && fileMatchesAllNames $@
fi
}
test -f "$file" && fileMatchesAllNames $patterns
请注意,不允许模式包含空格,以便脚本能够正常工作。
答案 3 :(得分:1)
您可以使用bash脚本:
#!/usr/bin/env bash
pattern="NODE-BB-4\|NODE-AA-1\|DUMMY"
words=3 # Number of patterns in $pattern
if (($(grep -o "$pattern" inputfile.txt | sort -u | wc -l) < $words)); then
echo "FAIL: Not all patterns found in input file"
else
echo "SUCCESS: All patterns found in input file"
fi
这使用管道命令:
grep -o "NODE-BB-4\|NODE-AA-1\|DUMMY" inputfile.txt | sort -u | wc -l
将返回inputfile.txt
中找到的唯一模式的数量。
答案 4 :(得分:1)
当节点作为文件中的第一列提供时,您可以使用grep
我想使用您的tr
方法,用不同的方式编写。
tr '|' '\n' <<< "${list_of_nodes}"
您可以使输出看起来像具有进程替换的文件
<(tr '|' '\n' <<< "${list_of_nodes}"
如果要使用文件的第一个字段检查这些字段,请剪切文件。
cut -d' ' -f1 file
您可以将outoput用于其他流程替代并使用grep
(选项x:完全匹配)。
grep -xvf <(cut -d' ' -f1 file) <(tr '|' '\n' <<< "${list_of_nodes}")
现在您可以使用sed
替换输出。
sed -r 's/.+/FAIL: &/'
零件:
grep -xvf <(cut -d' ' -f1 file) <(tr '|' '\n' <<< "${list_of_nodes}") |
sed 's/.+/FAIL/'
答案 5 :(得分:1)
另一个awk
$ awk 'NR==1 {n=split($0,x,"|");
for(i=1;i<=n;i++) nodes[x[i]];
next}
$1 in nodes {delete nodes[$1]}
END {for(k in nodes) print "fail: " k}' <(echo "$list_of_nodes") file
fail: DUMMY
删除所有看到的节点,并使用失败标记打印剩余的节点。
或者,另一种快速比较和输出缺失节点的方法
$ comm -23 <(tr '|' '\n' <<< "$list_of_nodes" | sort) <(cut -d' ' -f1 file | sort)
DUMMY
你可以对输出大小进行调整以使其失败或成功,但也许不会忽略丢失的内容也是有用的。
答案 6 :(得分:0)
使用sed
list_of_nodes='NODE-BB-4|NODE-AA-1|DUMMY'
sed $(echo "$list_of_nodes" | \
sed "s/|/\/!bA;\//g;s/^/ :B;\$bC;N;bB;:C;\//;s/$/\/!bA;d;:A;s\/.*\/fail\/ file/")
首先使用sed
从list_of_nodes创建一个sed命令:B;$bC;N;bB;:C;/NODE-BB-4/!bA;/NODE-AA-1/!bA;/DUMMY/!bA;d;:A;s/.*/fail/ file
执行它
sed $(...)