从文件中过滤唯一参数



我有一个包含url和如下参数的文件

https://example.com/endpoint/?param1=123&param2=1212
https://example.com/endpoint/?param3=123&param1=98989
https://example.com/endpoint/endpoint3/?param2=123
https://example.com/endpoint/endpoint2/?param1=123
https://example.com/endpoint/endpoint2/
https://example.com/endpoint/endpoint5/"//i.example.com/00/s/Nzk5WDEwMjQ=/z/47IAAOSwBu5hXIKF

,我只需要过滤具有唯一参数的url所需输出

http://example.com/endpoint/?param1=123&param2=1212
https://example.com/endpoint/?param3=123&param1=98989
https://example.com/endpoint/endpoint3/?param2=123

我设法只过滤带有grep参数的urlgrep -E '(?[a-zA-Z0-9]{1,9}=)'

,但我需要在同一时间过滤参数,所以我尝试与awk相同的正则表达式但是它给出了错误

awk '{sub(?[a-zA-Z0-9]{1,9}=)} !seen[$0]++'
<标题>

更新我很抱歉编辑所需的输出,但当我尝试脚本时,我发现他们的很多碳水化合物在我的文件中也需要过滤。我试着@James Brown做了一些编辑,直到最后一行看起来还不错,不幸的是它没有过滤

awk -F '?|&' '$2&&!a[$2]++'

和更清楚为什么输出对我有好处它选择了第一行,因为它至少有param1第二行,因为它至少有param33行,因为至少有param2这里的比较方法是选择唯一的参数不管它与其他参数是否有&字符

修改后的版本:

$ awk -F? '{                   # ? as field delimiter
split($2,b,/&/)            # split at & to get whats between ? and &
if(b[1]!=""&&!a[b[1]]++)   # no ? means no $2
print
}' file

按预期输出。原来的答案是:

短句:

$ awk -F? '$2&&!a[$2]++' file

解释:在?(-F?)分割记录,如果有第二个字段($2)和(&&),它是唯一的,到目前为止,通过计算数组a(!a[$2]++)中参数的实例,输出它。

EDIT: 当查询字符串中有?&时,下面的解决方案可能会有所帮助,我们希望同时考虑它们来删除重复项。

awk '
/?/{
match($0,/?[^&]*/)
val=substr($0,RSTART,RLENGTH)
match($0,/&.*/)
if(!seen[val]++ && !seen[substr($0,RSTART,RLENGTH)]++){
print
}
}' Input_file


解决方案2:(当我们在查询字符串中没有&参数时,以下解决方案可能会有所帮助)使用您显示的示例,请尝试以下awk程序。

awk 'match($0,/?.*$/) && !seen[substr($0,RSTART,RLENGTH)]++' Input_file

或以上可以缩短为如下:(根据Ed先生的建议):

awk 's=index($0,"?") && !seen[substr($0,s)]++' Input_file

解释:简单的解释是,使用awkmatch函数,它匹配从?到行尾的所有值。然后给它添加一个AND条件,以确保我们只从所有行中所有匹配的值中获得唯一的值。

对于gnu awk,您还可以匹配url,直到第一次出现问号,然后使用第一个参数([a-zA-Z0-9]{1,9}=[^&]+)的初始模式捕获随后的内容,然后匹配除&以外的任何字符

那么您可以使用!seen[$0]++部分的值为capture group 1

awk '
match($0, /https?://[^?]+?([a-zA-Z0-9]{1,9}=[^&]+)/, arr) && !seen[arr[1]]++
' file

输出
https://example.com/endpoint/?param1=123&param2=1212
https://example.com/endpoint/?param3=123&param1=98989
https://example.com/endpoint/endpoint3/?param2=123

使用awk可以检查字符串是否以协议开头并包含问号。

然后只获得第一个参数,您可以对?&进行分割,并对seen使用分割的第二部分

awk '
/^https?://[^?]*?/ && split($0, arr, /[?&]/) > 1 && !seen[arr[2]]++
' file

最新更新