使用 awk 检查排列

使用 awk 检查排列

我的问题是通过 shell 脚本确定某些字符串是否是彼此的排列,例如

1.Nf3 c5 2.e4 Nc6
1.e4 c5 2.Nf3 Nc6

正如您所看到的,排列是基于原子子串的。换句话说,我想知道两个字符串是否包含相同的子字符串而不考虑顺序。

AWK 是一种专为高级文本处理而设计的编程语言。因此出现的一个想法是将两个字符串拆分为数组:

{1., Nf3, c5, 2., e4, Nc6}
{1., e4, c5, 2., Nf3, Nc6}

并比较两者是否包含相同的元素。但我不确定这是否适合 awk 方式。

第二种方法是将第一个字符串拆分为模式{1., Nf3, c5, 2., e4, Nc6},并在第二个字符串中搜索所有模式,并根据这些匹配创建一个新字符串。毕竟我可以检查新字符串是否等于第一个字符串。 awk 中还有其他方法用于这种特定的文本处理吗?

答案1

我认为awk这不是正确的方法。只需分割字符串,对字符串元素进行排序,然后比较结果即可。

示例bash

$ split_and_sort() { sed -r 's/\</\n/g' | sort; }

$ split_sort_and_compare() {
    if [ "$(split_and_sort <<< "$1")" = "$(split_and_sort <<< "$2")" ]
    then echo "Match"
    else echo "No match"
    fi
}

$ split_sort_and_compare "1.Nf3 c5 2.e4 Nc6" "1.e4 c5 2.Nf3 Nc6"
Match

$ split_sort_and_compare "1.Nf3 c5 2.e4 Nc6" "1.e4 c5 2.Nf3 Nc5"
No match

这只是一个粗略的例子来说明我的想法,以及我自己对如何分割和比较字符串的解释。根据您的规则制作您自己的更复杂的功能。

答案2

仅供记录,这是一个 awk 解决方案(虽然不是很棘手),以防您需要将此解决方案集成到任何现有的 awk 项目中。

a="1.Nf3 c5 2.e4 Nc6"
b="1.e4 c5 2.Nf3 Nc6"
awk 'BEGIN{FS=""}{last=NF;for (i=1;i<=NF;i++) {if (NR==FNR) {a[i]=$i} else {b[i]=$i}}} \
{asort(a);asort(b)}END{{for (k=1;k<=last;k++) if (a[k]!=b[k]) nomatch++}{print (nomatch==0)?"match":"no match"}}' <(echo "$a") <(echo "$b")

如果你只是想比较这两个字符串,我会使用一些 bash 方式,或者像 xhienne 建议的答案,甚至像这样:

[[ $(sort <(grep -o . <<<"$a") |base64) == $(sort <(grep -o . <<<"$b") |base64) ]] && echo "match" || echo "differ"

在这两种情况下,逻辑是相同的。输入字符串按字符拆分,然后一一排序,并对这两个排序的字符串进行比较。

在上面的bash方式中,我想将排序后的字符串编码为base64并比较它们的base64值。

答案3

检查两个字符串是否包含相同字符的另一种方法是计算它们的 ASCII 值之和。

$ while read -rn1 char;do sumA+=$(printf '%d+' "'$char'");done <<<"1.Nf3 c5 2.e4 Nc6"
$ while read -rn1 char;do sumB+=$(printf '%d+' "'$char'");done <<<"1.e4 c5 2.Nf3 Nc6"

$ echo "$sumA"
49+46+78+102+51+39+99+53+39+50+46+101+52+39+78+99+54+39+
$ echo "$sumB"
49+46+101+52+39+99+53+39+50+46+78+102+51+39+78+99+54+39+

$ bc <<<"${sumB:0:-1}"
1114
$ bc <<<"${sumA:0:-1}"
1114

相同的数字和 = 相同的字符串。因此,通过比较这两个 bc 值,您可以得到匹配/不匹配条件。

如果字符串之间的一个字符不同,则 ascii 值之和将会不同:

$ while read -rn1 char;do sumC+=$(printf '%d+' "'$char'");done <<<"1.Nf3 q5 2.e4 Nc6" #q5 is different than string A
$ echo "$sumC"
49+46+78+102+51+39+113+53+39+50+46+101+52+39+78+99+54+39+
$ bc <<<"${sumC:0:-1}"
1128

相关内容