我有2个文件
档案1
abc
cde
efg
hij
jkl
文件2
abc
( * ) ( * ) ( * ) -- without the braces
efg
(*) hij -- without braces
(*) (*) lmn --- without braces
现在,在逐行比较两个文件的同时,即仅与file2的第一行比较的第一行file1
abc ---- abc
cde ---- * * *
当遇到* * *时,比较应移至下一行比较其他行
但是,在比较时
hij --- (*) hij or jkl --- (*) (*) lmn
hij
必须与File2的hij
进行比较,并且必须正常
并且jkl
必须与lmn
进行比较,并且必须给出不正确:在任何一种情况下都忽略*
或* *
我已经为相同的2个文件编写了脚本,但我无法检查*
。
你可以帮我解决同样的问题吗?
比较文件的脚本片段
# 1. Read lines from file1 as string, and file2 as comma-separated array.
while read -r a && IFS=, read -ra b <&3; do
# 2. If both empty lines, continue.
if [[ "$a" == "" && ${#b[@]} == 0 ]]; then
continue
fi
# 3. Start assuming diff.
diff=1
# 4. Loop fields in $b.
for e in ${b[@]}; do
# Compare field in $b with $a, if match then abort.
if [[ "$e" == "$a" ]]; then
diff=0
break
fi
done
# 5. If no match found, print line from $b.
if [[ $diff == 1 ]]; then
# Join array with <space>comma.
line=$(printf ", %s" "${b[@]}")
# Print line, excluding leading <space>comma.
printf "%s\n" "${line:2}"
fi
# Input argument one as file 1 to stdin, and argument two as file 2 to
# file descriptor 3.
done < "$1" 3<"$2"
答案 0 :(得分:0)
您的脚本已正确处理单个星号和双星号的情况。回想一下,您的脚本假定diff = 1,并且如果找到匹配,则仅更改为diff = 0。 ${b[@]}
只包含一个星号的元素比较不等于file1的输入行,这意味着这些元素正确地保留了原始假设(diff = 1)。但是,如果file1的输入行只包含一个星号,那么比较将导致匹配并设置diff = 0。但是,文件2中单个星号的含义会变得有些含糊不清;它是否意味着“匹配来自file1的文字单星号行”,或者它是否意味着“不匹配来自file1的任何行”?后一种意义似乎是你想要file2中的星号意思。如果您希望在这种奇怪的情况下保留这种意义,则必须添加一个显式测试以跳过file2中的星号字:
if [[ "$e" == '*' ]]; then continue; fi;
此测试将在for
循环的开始处进行。
关于三重星号的情况,听起来你想完全跳过这种情况。如上所述,目前来自file2的单星号元素被隐式跳过(因为它们与file1中的任何输入行都不匹配),这会留下diff = 1,并导致打印* * *
消息。为防止这种情况发生,您可以对* * *
添加明确的警示,如下所示:
if [[ ${#b[@]} -eq 3 && "${b[0]}" == '*' && "${b[1]}" == '*' && "${b[2]}" == '*' ]]; then continue; fi;
在空行检查之后,此测试将接近while
循环的开始。
答案 1 :(得分:0)
我更喜欢以下解决方案;您可以使用bash参数扩展功能来忽略简化脚本的前导星号。
参见bash手册,&#34;参数扩展&#34;。
如果您不想在输出中使用星号,则必须将if语句中使用的参数扩展的结果分配给单独的变量,并在比较中使用它。
while read -r a && IFS=, read -ra b <&3
do
# If both lines are empty, continue.
if [ -z "$a" ] && [ -z "$b" ]
then
continue
fi
# If b contains three stars, don't compare.
if [ "$b" == "***" ]
then
continue
fi
# compare a and b ignoring leading *
if [ "$a" == "${b##\*}" ]
then
echo "$a: ok"
else
echo "$a/$b: nok"
fi
done < "$1" 3<"$2"
此外,我会事先从文件中删除空行并检查两个输入文件的行数,以避免错误不匹配。