我有这个字符串:
DMT mode 4: 640x480 @ 60Hz 4:3, clock:25MHz progressive
我想从中提取模式编号(第一个 :) 之前的部分,在本例中为 4。正如您所期望的,模式编号可能是 1 或 2 位数字长,并且不能依赖它之前的文本字符长度完全相同。
我有一个有效的解决方案:
$picked = "DMT mode 4: 640x480 @ 60Hz 4:3, clock:25MHz progressive"
echo $picked | awk -F"mode " '{print $2}' | tr : '\n' | head -n1
但我觉得必须有一种更优雅的方法来做到这一点。优雅且易于学习,稍后再阅读(因此,可能不涉及正则表达式)。我梦想的命令是这样的:回声 $picked |在“模式”“:”之间
这里还有几个例子来展示需要可解析的输入范围:
CEA mode 7: 720x480 @ 60Hz 16:9, clock:27MHz x2 interlaced
CEA (native) mode 16: 1920x1080 @ 60Hz 16:9, clock:148MHz progressive
DMT mode 58: 1680x1050 @ 60Hz 16:10, clock:146MHz progressive
答案1
正则表达式将是更直接的解决方案:一些选项:
echo "$picked" | grep -oP '(?<=mode )\d+'
echo "$picked" | grep -oP '(?<=mode )[[:digit:]]+'
如果您不喜欢 PCRE 功能:
echo "$picked" | grep -oE 'mode [[:digit:]]+' | tr -d 'mode '
该tr
命令不会删除单词“模式”,它删除所有人物“模式”, ” ”。
如果你真的喜欢awk,迭代单词直到点击“模式”
echo "$picked" | awk '{for (i=1; i<NF; i++) if ($i == "mode") {print $(i+1); exit}}' | tr -d :
由于 shell 变量中已包含该字符串,因此 bash 参数替换如何:
tmp=${picked#*mode } # remove up to "mode "
value=${tmp%%:*} # remove the colon and everything after
然后
$ declare -p picked tmp value
declare -- picked="DMT mode 4: 640x480 @ 60Hz 4:3, clock:25MHz progressive"
declare -- tmp="4: 640x480 @ 60Hz 4:3, clock:25MHz progressive"
declare -- value="4"
参考3.5.3 Shell参数扩展在手册中(并掩盖了一些细节):
${var#pattern}
去除最短前缀匹配模式${var##pattern}
去除最长前缀匹配模式${var%pattern}
去除最短后缀匹配模式${var%%pattern}
去除最长后缀匹配模式
“最短”和“最长”之间的区别是关键。请注意,给定的字符串后缀中包含多个冒号——使用${tmp%:*}
仅删除最后的冒号及其后的字符。
答案2
如果您有支持 PCRE 样式正则表达式perl
的或其变体,您可以通过直接匹配后跟一个或多个数字来grep
选择值:mode
grep -oP 'mode\s+\K\d+'
我读到您不喜欢 RE,但是这是一个相当简单的模式,我将在这里解释:
- 一切 upto
\K
都是必须匹配的后向模式,但不包含在任何结果中 \s
匹配空白(通常空间或者标签);后缀+
需要其中一个或多个\d
匹配数字 (0
..9
);后缀+
需要其中一个或多个
如果您知道所需的值可能包含非数字文本,则可以替换\d+
为。[^:]+
此处,[^:]
匹配除冒号 ( :
) 之外的任何内容。
参考
答案3
简单直接的sed
解决方案是
sed -n 's/.*mode \([0-9]*\):.*/\1/p'
单个命令而不是三个 ( awk | tr | head
);如果您认为您的解决方案更容易阅读,我无法帮助您。
答案4
我喜欢已经给出的 Shell 参数扩展解决方案,但如果您不能使用 bash,以下 AWK 链将以相同的方式工作:
... |awk -F"mode " '{print$2}' | awk -F: '{print $1}'
第一个 awk 调用在“mode”上分割字符串并返回其后面的内容,
第二次调用将其拆分为 : 并返回其之前的内容。
对我来说,这比 Bash 参数扩展更具可读性。然而,它更加冗长,并且可能更慢(尽管众所周知 AWK 相当快,但启动它两次的开销将对其产生不利影响)。