删除bash中的反向匹配
我有一个文件,删除bash中的反向匹配,bash,awk,Bash,Awk,我有一个文件,list.txt,其中包含: 234 243 324 342 423 432 我如何才能找到反向模式(即432是234的反向模式)是否存在并删除反向模式?我尝试过 while IFS= read -r line; do reverse=$(echo $line|rev) if grep -q $reverse list.txt; then sed -i "s/$reverse//g" list.txt else : fi done < list.tx
list.txt
,其中包含:
234
243
324
342
423
432
我如何才能找到反向模式(即432是234的反向模式)是否存在并删除反向模式?我尝试过
while IFS= read -r line; do
reverse=$(echo $line|rev)
if grep -q $reverse list.txt; then
sed -i "s/$reverse//g" list.txt
else :
fi
done < list.txt
我想完成的事情可能吗?我的MWE是一个简短的列表,但是这个列表可以(并且将)显著增长。提前感谢。原始问题:删除输入中所有带反转的项目
删除文件中与任何其他字符串相反的所有字符串如下所示:
grep -Fvf <(rev list.txt) <list.txt >list.txt.new && mv list.txt.new list.txt
顺便说一句,请注意,在现实世界中,您应该使用
mktemp
为临时文件创建一个保证唯一/随机的名称,而不是像list.txt.new
这样的硬编码。这不仅解决了并发问题,还解决了问题。这里有一个awk
解决方案:
awk 'BEGIN{FS=""} !seen[$0]{s=""; for (i=NF; i>0; i--) s=s $i; seen[s]++; print}' file
说明:
:将输入文件分隔符设置为空字符串,以便输入中的每个字符都成为awk中的字段开始{FS=”“}
:如果SEED数组中未找到当前行!SEED[$0]{
:将s=”“;
初始化为空字符串s
:运行反向循环并在for(i=NF;i>0;i--)s=s$i
s
:将seed[s]++;
存储在数组s
seed
:打印当前行打印
awk'FNR==NR{pats[$0]=1;next}!(pats中的$0)“您如何期望输出中包含234
?您的文件包含432
,而234
是其反向,因此删除它显然是正确的。请记住,是的,我想保留其反向未被看到的数据。您介意解释更多while循环步骤吗?我有一个下面有点麻烦…是读取list.txt和rev list.txt,然后…?@RobS,循环从list.txt
读取一行(我们在文件描述符3上打开该行,因此使用@RobS进行读取),顺便说一句,它不仅仅是“未被看到”这是一个重要的区别,但文件中的这一点没有看到;也就是说,重要的区别(在您将示例输出放在问题中之前不清楚)是逻辑需要关心排序,而只考虑文件中特定点之前存在的其他行,而不是考虑文件中任何地方的其他行。我很欣赏解释和输入,它确实帮助了像我这样的新手。
#!/usr/bin/env bash
case $BASH_VERSION in ''|[123].*) echo "ERROR: Bash 4.0+ needed" >&2; exit 1;; esac
declare -A blacklisted=( )
while IFS= read -r orig <&3 && IFS= read -r rev <&4; do
[[ ${blacklisted[$orig]} ]] && continue
blacklisted[$rev]=1
printf '%s\n' "$orig"
done 3< list.txt 4< <(rev list.txt) >list.txt.new && mv list.txt.new list.txt
awk 'BEGIN{FS=""} !seen[$0]{s=""; for (i=NF; i>0; i--) s=s $i; seen[s]++; print}' file
234
243
324