如何删除包含 2 个匹配字符串的重复文件但保留其余文件?

如何删除包含 2 个匹配字符串的重复文件但保留其余文件?

我有一个问题,我不知道如何解决。我有一个包含 1000 个文件的目录,每个文件都包含一个带有 URL 参数的 URL:

文件一:

example.com/car/?wheel=tyre

文件2:

example.com/car/?wheel=rim

文件3:

test.com/food/?fruit=apple

文件4:

test.com/food/?fruit=banana

文件5:

test.co.uk/car/interior=chair

文件6:

example.co.uk/car/interior=chair

我想删除包含相同域名和参数的重复文件,但保留第一个。参数内的项目,例如。轮胎、轮辋、苹果、香蕉和椅子应该被忽略。所以所需的输出如下:

文件一:

example.com/car/?wheel=tyre

文件3:

test.com/food/?fruit=apple

文件5:

test.co.uk/car/interior=chair

文件6:

example.co.uk/car/interior=chair

文件 2 已被删除,因为它与文件 1 具有相同的域名和 URL 参数名称。文件 4 已被删除,因为它与文件 3 具有相同的域名和 URL 参数名称。文件 5 和 6 被保留,因为它们使用不同的域,即使它们使用相同的 URL 参数。

我想我需要首先遍历目录中的所有文件:

FILES=data/urls/*
for i in $FILES
do
  cat $i | *Check for matching domain, then matching parameter*
else
 rm $i
fi
done

或者可以使用 for 循环搜索域名,然后使用 uniq 嵌套 for 循环来检查参数。但是我不知道该怎么做。

我有什么想法可以做到这一点吗?

编辑: 我已将所有 url 添加到一个文件中,以便更轻松地使用它们:

sed -i -e '$a\' *.txt
cat * > all.txt

编辑2: 某些 URL 的路径中包含多个文件夹,例如。

www.example.com/1/2/3/4/5/?l=123
www.example.com/1/2/3/?1=AAA

答案1

像这样的小 Bash 脚本应该可以做到:

#!/bin/bash

declare -A a                             # declare associative array 
for i in *; do                           # loop through files in directory

  read -r url < "$i"                     # read the url from the file
  domain=${url%%/*}                      # delete longest match from back
  param=${url##*/}                       # delete longest match from start
  param=${param%%=*}                     # delete "=value" from param
  k=$domain$param                        # construct key

  if [[ -n $k && -z ${a[$k]} ]]; then    # check its prior use as key k
    a[$k]=1                              # new key: mark it as such
  else                                   # known/faulty key: delete the file
    echo Delete "$i"                     # Replace with: rm "$i" if satisfied
  fi
done

答案2

对于一个文件中的所有行,您可以使用以下 Perl 代码:

perl -nle '($d,$p)=m{^(\S+?)/\S+/\??(\w+)=}; $a{"$d$p"}=$_ if "$d$p";
END {print $a{$_} for (keys %a)}' input

input是数据文件,但您可以通过管道输入此 Perl 命令。工作很简单。正则表达式首先用于隔离域和首先每个条目的参数。然后整行被写入字典,其中早期孤立的部分是关键。任何较早的值都会被覆盖。最后打印哈希值。

它产生以下输出:

test.co.uk/car/interior=chair
www.example.com/1/1/?l=spanish
example.com/car/?wheel=rim
www.example.com/1/1/?selectedTab=live&selectedStream=1
example.co.uk/car/interior=chair
test.com/food/?fruit=banana

从这个输入:

example.com/car/?wheel=tyre
example.com/car/?wheel=rim
test.com/food/?fruit=apple
test.com/food/?fruit=banana
test.co.uk/car/interior=chair
example.co.uk/car/interior=chair
www.example.com/1/1/?l=thai 
www.example.com/1/1/?l=thai
www.example.com/1/1/?l=ukrainian
www.example.com/1/1/?l=turkish
www.example.com/1/1/?selectedTab=live&selectedStream=1
www.example.com/1/1/?l=ukrainian
www.example.com/1/1/?l=turkish
www.example.com/store/?l=turkish
www.example.com/1/1/storecommon.js?v=aHpFwmVHuavD&l=dutch
www.example.com/1/1/2/0/?l=english
www.example.com/1/1/9/0/?l=english
www.example.com/1/1/?l=spanish

存在一个故障?v=aHpFwmVHuavD&l=dutch,它由两个参数组成。它们可能应该被一一分解和处理,这使得事情变得更加复杂。确保情况并非如此。另请注意,domain.comwww.domain.com不是实际上是一样的。

相关内容