从固定模式字符串中提取多个值

Web*_*ser 7 regex bash awk substring

我想从命令输出的最后一位中解析出 3 条信息wget。例如:

\n
2022-12-26 19:14:44 (13.7 Mb/s) - \xe2\x80\x98somelibrary.min.js\xe2\x80\x99 saved [1077022]\n
Run Code Online (Sandbox Code Playgroud)\n

我能够获取日期/时间,因为它是固定长度。我无法提取估计的传输速度 ( 13/7) 和文件大小 ( 1077022) 值。

\n
STR="2022-12-26 19:14:44 (13.7 Mb/s) - \xe2\x80\x98somelibrary.min.js\xe2\x80\x99 saved [1077022]"\necho date/time is ${STR::19}\n
Run Code Online (Sandbox Code Playgroud)\n

我想剩余的子字符串提取需要借助正则表达式来完成,但我无法弄清楚。是否有一条仅使用 awk、sed 等 *nix 实用程序的可行路径?

\n

我尝试过 awk:

\n
echo "(13.7 Mb/s)" | awk '$0 ~ /(.* Mb\\/s)/ {print $1}'\n
Run Code Online (Sandbox Code Playgroud)\n

但我得到的(13.7不仅仅是数字。

\n

Gor*_*son 8

您可以使用 bash 的正则表达式匹配来做到这一点,( )在 RE 中使用捕获相关部分并${BASH_REMATCH[n]}获取它们:

\n
str="2022-12-26 19:14:44 (13.7 Mb/s) - \xe2\x80\x98somelibrary.min.js\xe2\x80\x99 saved [1077022]"\n\npattern=\'([-0-9]+ [:0-9]+) \\(([^)]+)\\) .*\\[([0-9]+)\\]\'\nif [[ "$str" =~ $pattern ]]; then\n    echo "date/time is ${BASH_REMATCH[1]}"\n    echo "transfer speed is ${BASH_REMATCH[2]}"\n    echo "file size is ${BASH_REMATCH[3]}"\nelse\n    echo "The string is not in the expected format"\nfi\n
Run Code Online (Sandbox Code Playgroud)\n

顺便说一句,我建议使用小写或混合大小写的变量名称,以避免与许多具有特殊功能的全大写名称发生冲突,并通过shellcheck.net运行脚本运行脚本以查找常见错误。

\n


anu*_*ava 6

awk应该适合你:

\n
s="2022-12-26 19:14:44 (13.7 Mb/s) - \xe2\x80\x98somelibrary.min.js\xe2\x80\x99 saved [1077022]"\nawk -F \'[][()[:blank:]]+\' \'{\n  printf "DateTime: %s %s, Speed: %s, Size: %s\\n", $1, $2, $3, $(NF-1)\n}\' <<< "$s"\n\nDateTime: 2022-12-26 19:14:44, Speed: 13.7, Size: 1077022\n
Run Code Online (Sandbox Code Playgroud)\n

分解:

\n
    \n
  • -F \'[][()[:blank:]]+\'将 1+ 或 或 或 或 空格设置[]输入(字段)分隔符
  • \n
\n


Rav*_*h13 6

使用您显示的示例,请尝试以下awk代码。用 GNU 编写和测试awk。这是在线演示使用正则表达式的

\n
s="2022-12-26 19:14:44 (13.7 Mb/s) - \xe2\x80\x98somelibrary.min.js\xe2\x80\x99 saved [1077022]"\n\nawk \'\nmatch($0,/([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}) \\(([^)]*).*\\[([0-9]+)/,arr){\n  print "DateTime: "arr[1] ", Speed: " arr[2] ", Size: "arr[3]\n}\n\' <<< "$s"\n
Run Code Online (Sandbox Code Playgroud)\n


Gil*_*not 5

使用 Perl 和命名捕获组

\n
s="2022-12-26 19:14:44 (13.7 Mb/s) - \xe2\x80\x98somelibrary.min.js\xe2\x80\x99 saved [1077022]"\n\nperl -nE \'\n    say join "\\n",\n    map { "$_: $+{$_}" }\n    keys %+\n    if m/\n        (?<dateTime>\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}:\\d{2})\\s+\\(\n        (?<speed>\\d+\\.\\d+).*\\[\n        (?<size>\\d+)\n    /x\n\' <<< "$s"\n
Run Code Online (Sandbox Code Playgroud)\n

输出

\n
speed: 13.7\ndateTime: 2022-12-26 19:14:44\nsize: 1077022\n
Run Code Online (Sandbox Code Playgroud)\n

说明

\n

请参阅regex101 说明

\n