我有一个包含url和如下参数的文件
https://example.com/endpoint/?param1=123¶m2=1212
https://example.com/endpoint/?param3=123¶m1=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¶m2=1212
https://example.com/endpoint/?param3=123¶m1=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
解释:简单的解释是,使用awk
的match
函数,它匹配从?
到行尾的所有值。然后给它添加一个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¶m2=1212
https://example.com/endpoint/?param3=123¶m1=98989
https://example.com/endpoint/endpoint3/?param2=123
使用awk
可以检查字符串是否以协议开头并包含问号。
然后只获得第一个参数,您可以对?
和&
进行分割,并对seen
使用分割的第二部分
awk '
/^https?://[^?]*?/ && split($0, arr, /[?&]/) > 1 && !seen[arr[2]]++
' file