从文件中过滤唯一参数

filter unique parameters from file

我的文件包含如下网址和参数

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

而且我只需要过滤具有唯一参数的网址 所需的输出

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

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

但我需要同时过滤参数,所以我尝试使用具有相同正则表达式的 awk 但它给出了错误

awk '{sub(\?[a-zA-Z0-9]{1,9}\=)} !seen[[=12=]]++'

更新

我很抱歉编辑了所需的输出,但是当我尝试脚本时,我发现我文件中的大量 carbege 也需要过滤。 我尝试了@James Brown 进行了一些编辑,它看​​起来不错,直到最后一行,不幸的是它没有过滤它

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

更清楚为什么输出对我有好处 它选择第一行是因为它至少有 param1 第二行,因为它至少有 param3 3 行,因为它至少有 param2 这里的比较方法是只选择唯一参数,无论它是否与其他参数连接 & char 或 not

编辑: 当查询字符串中存在 ? 以及 & 时,以下解决方案可能会有所帮助它,我们想考虑将它们都用于删除重复项。

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


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

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

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

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

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

需求修改后的编辑版本:

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

按预期输出。原答案是:

一个短的:

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

解释:在 ? (-F?) 处拆分记录,如果有第二个字段 (</code>) 和 (<code>&&) 它到目前为止是唯一的统计数组a(!a[]++)中参数的实例,输出。

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

之外的任何字符

然后你可以使用 !seen[[=16=]]++ 部分和捕获组 1 的值。

awk '
match([=10=], /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([=12=], arr, /[?&]/) > 1 && !seen[arr[2]]++
' file