2

我想知道你能不能帮忙。我是 bash 脚本的新手。

我希望能够比较两个列表。File1.txt 将包含许多参数的列表,而 file2.txt 将仅包含这些参数的一部分。

文件1.txt

dbipAddress=192.168.175.130
QAGENT_QCF=AGENT_QCF
QADJUST_INVENTORY_Q=ADJUST_INVENTORY_Q
QCREATE_ORDER_Q=CREATE_ORDER_Q
QLOAD_INVENTORY_Q=LOAD_INVENTORY_Q

文件2.txt

AGENT_QCF
ADJUST_INVENTORY_Q
CREATE_ORDER_Q

我想检查 file1.txt 中的所有 Q 是否都包含在 file2.txt 中(在 之后=)。如果不是,则 bash 脚本应该停止并echo显示一条消息。

因此,在上面的示例中,脚本应该停止,因为 File2.txt 不包含以下 Q: LOAD_INVENTORY_Q

file1.txt 或 file2.txt 中的 Q 不遵循任何特定顺序。

4

5 回答 5

2

下面的命令将打印出 file1.txt 中=没有出现在 file2.txt 中的值(出现在 之后的任何内容)的行。

[me@home]$ awk -F= 'FNR==NR{keys[$0];next};!($2 in keys)' file2.txt file1.txt
dbipAddress=192.168.175.130
QLOAD_INVENTORY_Q=LOAD_INVENTORY_Q

命令分解:

awk -F= 'FNR==NR{keys[$0];next};!($2 in keys)' file2.txt file1.txt
    --- ---------- -------------
     | | |
改变| file1.txt 中的目标行
分隔符 | 第二列(由`=`分隔)做
  到'=' | 在 keys[] 数组中不存在。
           将每一行存储在    
           file2.txt 作为键
           在键[] 数组中

要进行更详细的操作,假设您希望将命令作为预过滤器运行以确保文件在继续执行脚本之前有效,您可以使用:

awk -F= 'FNR==NR{K[$0];N++;next};!($2 in K) {print "Line "(NR-N)": "$0; E++};END{exit E}' file2.txt file1.txt
ERRS=$?
if [ $ERRS -ne 0 ]; then  
    # errors found, do something ...
fi

这将打印出 file1.txt 中所有不符合要求的行(包括行号),并返回与不符合行数匹配的退出代码。这样,您的脚本可以通过检查$?并相应地响应来轻松检测错误。

示例输出:

[me@home]$ awk -F= 'FNR==NR{K[$0];N++;next};!($2 in K) {print "Line "(NR-N)": "$0;E++};END{exit E}' file2.txt file1.txt
Line 1: dbipAddress=192.168.175.130
Line 5: QLOAD_INVENTORY_Q=LOAD_INVENTORY_Q
[me@home]$ echo $?
2
于 2013-05-28T12:32:43.200 回答
1

您可以使用cut仅获取 之后的部分=comm可用于输出第一个文件中包含的行,但不能输出第二个文件中包含的行:

grep ^Q File1.txt | cut -d= -f2- | sort | comm -23 - <(sort File2.txt)
于 2013-05-28T12:51:06.457 回答
0

以下命令行表达式将过滤掉 file2.txt 中出现的行,而不是 file1.txt 中出现的行:

cat file1.txt | grep -Fvf file2.txt | grep '^Q'

解释:

-F : match patterns exactly (no expansion etc.) ; much faster
-v : only print lines that don't match
-f : get your patterns from the file specified

| grep '^Q' : pipe the output into grep, and look for lines that start with "Q"

这并不完全是“在...时停止 bash 脚本”,因为它会处理并打印每个不匹配的情况;此外,它不会测试模式前面是否有“=” - 但我希望它有用。

于 2013-05-28T12:13:17.883 回答
0

假设中的相关行file1.txt始终以 a 开头Q

grep "^Q" file1.txt | while IFS= read -r line
do
    what=${line#*=}
    grep -Fxq "$what" file2.txt || echo "error: $what not found"
done

输出:

error: LOAD_INVENTORY_Q not found
于 2013-05-28T12:23:08.383 回答
0

这是另一种方式:

missing=($(comm -23 <(awk -F= '/^Q/ {print $2}' file1.txt | sort) <(sort file2.txt)))
if (( ${#missing[@]} )); then
  echo >&2 "The following items are missing from file2.txt:"
  printf '%s\n' "${missing[@]}"
  exit 1
fi
于 2013-05-28T12:41:39.393 回答