从文件中过滤唯一参数
filter unique parameters from file
我的文件包含如下网址和参数
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
而且我只需要过滤具有唯一参数的网址
所需的输出
http://example.com/endpoint/?param1=123¶m2=1212
https://example.com/endpoint/?param3=123¶m1=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
解释: 简单的解释是,使用 awk
的 match
函数匹配来自 ?
直到行尾值。然后向其添加一个 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¶m2=1212
https://example.com/endpoint/?param3=123¶m1=98989
https://example.com/endpoint/endpoint3/?param2=123
使用 awk
您可以检查字符串是否以协议开头并包含问号。
然后只获取第一个参数,你可以在 ?
和 &
上拆分,并将拆分的第二部分用于 seen
awk '
/^https?:\/\/[^?]*\?/ && split([=12=], arr, /[?&]/) > 1 && !seen[arr[2]]++
' file
我的文件包含如下网址和参数
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
而且我只需要过滤具有唯一参数的网址 所需的输出
http://example.com/endpoint/?param1=123¶m2=1212
https://example.com/endpoint/?param3=123¶m1=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
解释: 简单的解释是,使用 awk
的 match
函数匹配来自 ?
直到行尾值。然后向其添加一个 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¶m2=1212
https://example.com/endpoint/?param3=123¶m1=98989
https://example.com/endpoint/endpoint3/?param2=123
使用 awk
您可以检查字符串是否以协议开头并包含问号。
然后只获取第一个参数,你可以在 ?
和 &
上拆分,并将拆分的第二部分用于 seen
awk '
/^https?:\/\/[^?]*\?/ && split([=12=], arr, /[?&]/) > 1 && !seen[arr[2]]++
' file