【问题标题】:Search after a match once per line每行搜索一次匹配
【发布时间】:2023-03-13 02:18:01
【问题描述】:

我正在尝试创建一个脚本以在特定单词“statusDescription”之后获取所有 Apache 响应,但我有一个问题,我将某些行的输出重复为匹配的单词或响应可能写了 2 次@相同行

日志“1行”示例:

GET/en?status=1&newMainBalance=5486&serviceAmount=700&ExternalTrxId=asdf&PgTrxId=tfpsadf&amount=0&statusDescription=Failed&customerCode=1.1&newDedicatedBalance=0&secureHash=56a7sdyf&paidAmount=1000&responseMsg=%a1%a1%A1(PG_ID)&language=enHTTP/1.1"200186243**1/1210669**1"-""-""-""https://example.com.eg?statusDescription=Failed&externalTrxId=123&status=203&secureHash=asdf&pgTrxId=asdf

我尝试了下面的命令来获得“statusDescription”和“&”之间的任何匹配

cat test.txt  | perl -nle'print $1 while /statusDescription(.*?)\&/g'
cat test.txt  | perl -nle'print $1 while /statusDescription(.*?)\&/g'

输出:

=失败
=失败

i 除了结果只有 1 行,就像

=失败

=失败=失败

【问题讨论】:

标签: linux string perl search


【解决方案1】:

您使用了没有值的-l 选项。引用perlrun:

如果省略八进制数,则将$\ 设置为$/ 的当前值

默认为\n。因此,每次打印都会自动附加一个\n

$  echo 'Match=once& should only Match=twice& once' | perl -nle 'print "MATCH ->$1<-" while /Match(.*?)&/g'
MATCH ->=once<-
MATCH ->=twice<-

# the same without -l
$ echo 'Match=once& should only Match=twice& once' | perl -ne 'print "MATCH ->$1<-" while /Match(.*?)&/g'
MATCH ->=once<-MATCH ->=twice<-

# if your post-processing requires matches from different lines to appear
# on separate lines then append a conditional print "\n" at the end
$ echo 'Match=once& should only Match=twice& once' | perl -ne 'print "MATCH ->$1<-" while /Match(.*?)&/g; print "\n" if $1'
MATCH ->=once<-MATCH ->=twice<-
$ echo 'nomatch=once& should only nomatch=twice& once' | perl -ne 'print "MATCH ->$1<-" while /Match(.*?)&/g; print "\n" if defined $1'
$

对于$/(输入记录分隔符)和$\(输出记录分隔符)另见perlvar

【讨论】:

  • 非常感谢您的支持,请您再帮我做一件事。它对我有用,但我还面临 1 个问题,即当 Statusdescription 位于行尾时它返回 null 。例如: GET/en?status=1&newMainBalance=5486&serviceAmount=700&ExternalTrxId=asdf&PgTrxId=tfpsadf&amount=0&statusDescription=Failed” 所以它不符合“&”的标准我可以让它更通用,只匹配“StatusDescription=”之后的 1 个单词" 和之前的 "&" 与否
  • 这实际上是另一个问题,但您可以尝试在&amp; 上拆分行,然后在各个部分上进行匹配。例如。 perl -ne 'foreach my $p (split(/&amp;/)) { print "$1\n" if $p =~ /^statusDescription(=.*)/; }'
  • 但是如果我在 "&" 上拆分行,它会复制输出,以防我在同一行上有 2 个状态描述(一个在 & 之前,另一个在行尾)并且我需要在第一场比赛后终止以获得准确的结果非常感谢您的提前支持,您真的帮了我很多
  • 好的,您只想查找并打印第一个匹配项?然后应该这样做perl -ne 'foreach my $p (split(/&amp;/)) { if ($p =~ /^statusDescription(=.*)/) { print "$1\n"; last } }'
  • 你好 Stefan Becker 我遇到了一个新问题,我发现有一段时间重复了,所以我需要添加一个新匹配来过滤它,所以我需要像以前一样获取状态描述并添加 pgtrxid 是这样的( pgTrxId=asdf&statusDescription=Failed) 请记住忽略 pgtrxid 的大小写敏感
【解决方案2】:

-l 具有在每个print 之后打印换行符的效果。

以下将打印所请求 URL 的(第一个)statusDescription 字段的值(同时忽略引荐来源网址)。它甚至会为您正确解码该值(如果它包含转义字符,例如 +%20)。

perl -MURI -MURI::QueryParam -nle'
   my ($request_url) = /^\S+\s+(\S+)/
      or next;
   $request_url = URI->new($request_url, "http");
   my $status = $request_url->query_param("statusDescription")
      or next;
   print $status;
' test.txt

【讨论】:

    猜你喜欢
    • 2011-09-11
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-30
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    相关资源
    最近更新 更多