scrambledA.txt
我的列表中有一个数据,如下所示:
efrrsu
aehmmr
aeeglnr
alnors
acflno
aaahmy
aceimru
1469en
aelprsy
cehrry
以及wordlistC.txt
包含许多键值对的对应:
...-...
...-...
1469en-ne1469
aaahmy-yamaha
aceimru-maurice
acflno-falcon
aeeglnr-general
aehmmr-hammer
aelprsy-players
alnors-larson
cehrry-cherry
efrrsu-surfer
...-...
...-...
我正在尝试将 myscrambledA.txt
与 中的正确单词相匹配wordlistC.txt
。首先我尝试过
grep -f scrambledA.txt wordlistC.txt | cut -d'-' -f2
scrambledA.txt
但它没有按照我需要的顺序提供输出。然后我想我必须用 for 循环做一些事情,但无法让它工作 - 我做错了什么?
for line in $(cat "scrambledA.txt")
do
#grep -f "$line" wordlistC >> scrambledBB.txt
#echo $line | grep -f wordlistC.txt >> scrambledBBB.txt
done
预期输出是
surfer
hammer
general
larson
falcon
yamaha
maurice
ne1469
players
cherry
答案1
严格来说,你是按照输入文件中出现的顺序获取单词。只是您的“输入文件”是grep
单词列表文件,而不是乱序单词列表。
您当前使用grep
其-f
选项提供的是乱序单词列表,这实际上并不是您想要匹配的模式。您想要匹配的模式是单词列表文件中的键(-
每行第一个之前的字符串)。你想要匹配那些对照打乱文件中的单词来挑选出相应的未打乱的字符串。
我们可以相当容易地做到这一点,awk
只需将单词列表读入关联数组,然后从该数组中的乱码文件中查找每行读取的单词:
$ awk -F - '!wordlist_processed { dict[$1]=$2; next }
{ print $0 in dict ? dict[$0] : "UNKNOWN WORD" }
' wordlistC.txt wordlist_processed=1 scrambledA.txt
surfer
hammer
general
larson
falcon
yamaha
maurice
ne1469
players
cherry
UNKNOWN WORD
这还将额外打印出未作为单词列表中的键出现的任何乱序单词的字符串。
一种完全不同的方法是将单词列表转换为一个sed
脚本,只需替换输入中的单词:
$ sed 's,\([^-]*\)-\(.*\),s/^\1$/\2/;t,' wordlistC.txt | sed -f /dev/stdin scrambledA.txt
surfer
hammer
general
larson
falcon
yamaha
maurice
ne1469
players
cherry
第一个sed
命令生成一个脚本,第二个命令sed
将其应用于扰乱的单词。考虑到问题中的示例(...
删除了 -entries),脚本将如下所示:
s/^1469en$/ne1469/;t
s/^aaahmy$/yamaha/;t
s/^aceimru$/maurice/;t
s/^acflno$/falcon/;t
s/^aeeglnr$/general/;t
s/^aehmmr$/hammer/;t
s/^aelprsy$/players/;t
s/^alnors$/larson/;t
s/^cehrry$/cherry/;t
s/^efrrsu$/surfer/;t
(请注意,我们按原样使用单词列表中的单词,这意味着键需要是正确的正则表达式,并且未加扰的单词需要有效才能包含在替换命令的右侧sed
。)
正如您所看到的,每次替换都会匹配一行上特定的单独打乱的单词,并将其替换为未打乱的单词。如果进行了替换,则每次替换后的裸t
命令将分支到脚本末尾。这是为了避免在任何输入行上进行多次替换。
在上述两种方法中,我们“将单词列表”应用于打乱的单词以对其进行解读。不是相反,这就是你在问题中所做的。
答案2
如果您wordlistC.txt
可以完全读入内存,您可以scrambledA.txt
使用以下命令解扰您的内容awk
:
awk -F'-' '
# Save lookup key/value
FNR==NR { w[$1]=$2 }
# Lookup or error
FNR<NR { if($1 in w) { print w[$1] } else { print "Unknown:", $1 } }
' wordlistC.txt scrambledA.txt
输出
surfer
hammer
general
larson
falcon
yamaha
maurice
ne1469
players
cherry
答案3
当您需要保留列表的顺序时,一种常见的技术是添加数字在处理之前对其进行处理。安排保留这些数字并使用它们种类处理完之后就可以切数字出来了。
nl scrambledA.txt | … | sort -k1n | cut -f2
您可以使用join
根据字段的值合并两个文件中的行。请注意,两个输入都必须根据公共字段进行排序。加入时,保留扰乱文件中的编号以及单词列表中解扰的单词:您不再需要扰乱的单词。
nl scrambledA.txt | sort -k2 |
join -t $'\t' -1 2 -2 1 -o 1.1,2.2 - <(<wordlistC.txt tr - \\t | sort) |
sort -t $'\t' -k1n | cut -f2
答案4
使用乐(以前称为 Perl_6)
#taking scrambledA.txt inline:
~$ raku -ne 'BEGIN my @scrambled = <efrrsu aehmmr aeeglnr alnors acflno aaahmy aceimru 1469en aelprsy cehrry>;
state %hash;
%hash.append: $_.split("-");
END put %hash{$_} // next for @scrambled;' wordlistC.txt
或者:
#taking scrambledA.txt using a filepath:
~$ raku -ne 'BEGIN my @scrambled = "/path/to/scrambledA.txt".IO.lines;
state %hash;
%hash.append: $_.split("-");
END put %hash{$_} // next for @scrambled;' wordlistC.txt
上面是用 Raku(Perl 编程语言家族的成员)编写的答案。 Raku 使用-ne
非自动打印(awk
类似)逐行命令行标志进行调用。
与 Perl 一样,Raku 也内置了哈希(即关联数组/字典)。上面使用的策略是将加扰的单词作为@
-sigiled 数组获取,以维持所需的输出顺序(采用上述两种方式之一获取加扰的单词)。那么联想词表就是split
创建一个%hash
,其中乱码词为key
,明文词为value
。
最后在END
块中,我们@scrambled
使用 迭代数组for
:通过 哈希在哈希中查找每个元素(键) ,并输出%hash{$_}
相应的值(如果找到)。value
输入示例(scrambledA.txt):
efrrsu
aehmmr
aeeglnr
alnors
acflno
aaahmy
aceimru
1469en
aelprsy
cehrry
示例输入(wordlistC.txt):
1469en-ne1469
aaahmy-yamaha
aceimru-maurice
acflno-falcon
aeeglnr-general
aehmmr-hammer
aelprsy-players
alnors-larson
cehrry-cherry
efrrsu-surfer
示例输出:
surfer
hammer
general
larson
falcon
yamaha
maurice
ne1469
players
cherry
使用(“定义-或”下一步)wordlistC.txt
跳过无法在文件中查找的乱序单词。您可以通过将“定义或”运算符的右侧更改为(空字符串)来为不匹配项保留空行,// next
而不是仅返回匹配项。否则,如果您想要更详细的反馈,请添加您选择的字符串,如下所示:next
//
""
END put %hash{$_} // "Unknown: $_" for @scrambled;`
https://docs.raku.org/language/hashmap#Hashes_and_maps
https://docs.raku.org/
https://raku.org