【问题标题】:Bash RegEx Lookahead/Lookbehind CPU InformationBash RegEx Lookahead/Lookbehind CPU 信息
【发布时间】:2013-10-02 19:06:08
【问题描述】:

我只是将 cat /proc/cpuinfo 的输出存储到 bash 脚本中的变量中。

/proc/cpuinfo:

processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 58 model name : Intel(R) Core(TM) i5-3230M CPU @ 2.80GHz stepping : 9 cpu MHz : 2562.759 cache size : 6144 KB fpu : yes fpu_exception : yes cpuid level : 5 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx rdtscp lm constant_tsc up rep_good nopl pni monitor ssse3 lahf_lm bogomips : 5125.51 clflush size : 64 cache_alignment : 64 address sizes : 36 bits physical, 48 bits virtual power management:

当我将信息收集到文本文件并 grep 时:

grep -P '(?<=model name\s:\s)[\w ()-]*(?=CPU)' infotext.txt

我得到一个匹配:

model name  : **Intel(R) Core(TM) i5-3230M** CPU @ 2.60GHz

但是,在我的 bash 脚本中对此进行测试后,我找不到匹配项:

regex='(?<=model name\s:\s).*(?=CPU)'

if [[ $line =~ $regex ]]; then
     modelName=${BASH_REMATCH[1]}
fi

这可能与将 /proc/cpuinfo 的输出转换为文本文件与将其简单地存储在变量 cpuInfo=$(cat /proc/cpuinfo) 中的区别有关吗?

如果不是,我在 bash 中的正则表达式的格式是否会导致问题? (我可能需要另一种方式来对“型号名称:”和“CPU”进行前瞻/后瞻)。

【问题讨论】:

  • 您尝试过if [[ $line =~ "(?&lt;=model name\s:\s)[\w ()-]*(?=CPU)" ]]; then 吗? (将单引号改为双引号)
  • Bash 正则表达式单独使用,不包含在's 中。顺便说一句,我不确定 bash 正则表达式是否支持前瞻。
  • 我试过用双引号,是的。考虑到正则表达式中的括号,单独使用正则表达式会产生错误。我可以尝试删除它们并以不同的方式匹配它们。在大多数情况下,我使用变量 regex='regexdata' 然后运行比较 - 这很有效。
  • 关心:cpuInfo=$(cat /proc/cpuinfo) 的效果与cpuInfo="$(cat /proc/cpuinfo)" 不同!!! (注意 引号)
  • @F.Hauri,我没有在变量中使用双引号。我在正则表达式上使用引号。我只是询问输出到文件和变量之间的差异是否改变了我解析它的方式。

标签: regex bash


【解决方案1】:

我的目的:

注意单引号或双引号的使用!

cp /proc/cpuinfo /dev/shm/infotext.txt

while read line ;do
    [ "$line" != "${line#model name}" ] && fld=${line#*: } &&
        modelName+=$'\n'${fld//CPU*}
  done </dev/shm/infotext.txt

比:

echo "${modelName#$'\n'}"
Intel(R) Core(TM)2 Duo 
Intel(R) Core(TM)2 Duo 

(有两个核心)

我不使用overkill bash re,因为这种方式明显更轻。

但如果你真的想这样做:

unset modelName
while read line ;do
    [[ "$line" =~ model.name[$'\t ']*:' '*(.*)CPU ]] &&
        modelName+=$'\n'${BASH_REMATCH[1]}
  done </dev/shm/infotext.txt

echo "${modelName#$'\n'}"
Intel(R) Core(TM)2 Duo 
Intel(R) Core(TM)2 Duo 

现在好了:

unset line modelName
time for ((i=1000;i--;)) ;do
    while read line ;do
        [[ "$line" =~ model.name[$'\t ']*:' '*(.*)CPU ]] &&
            modelName+=$'\n'${BASH_REMATCH[1]}
      done </dev/shm/infotext.txt
  done

real    0m2.001s
user    0m1.904s
sys     0m0.088s

基于 bash 正则表达式的 1000 x 1 测试需要 2 秒

unset fld line modelName
time for ((i=1000;i--;)) ;do
    while read line ;do
        [ "$line" != "${line#model name}" ] && fld=${line#*: } &&
            modelName+=$'\n'${fld//CPU*};
      done </dev/shm/infotext.txt
  done

real    0m1.780s
user    0m1.716s
sys     0m0.060s

1000 x 1 测试 + 2 字符串操作需要 1.8 秒。

【讨论】:

  • 我喜欢你回答这个问题的方式。我是 bash 狂热者,最近我开始在 bash 中使用正则表达式,因为它非常强大,但也很棘手。非常感谢,我会在以后的努力中考虑这一点!
【解决方案2】:

正则表达式不适用于引号,但可以使用变量,[\w] 似乎不支持修改正则表达式给出结果:

re='model name\s:\s(.*?)CPU'
[[ $line =~ $re ]]
echo "${BASH_REMATCH[1]}"

【讨论】:

  • 我已经做了一个变量并修改了我的正则表达式,没有'\w'。有趣的是,即使该方法不使用正常标准的前瞻/后视,在 grep 中它与字符串中的模型名称和 CPU 匹配,但在 bash 中却不匹配。
  • 按照我的回答 ${BASH_REMATCH[0]} 将获得所有匹配,但 ${BASH_REMATCH[1]} 将仅捕获括号之间的第一组
  • 它会的。这就是为什么我的问题包括我对 bash 中正则表达式的理解是否不正确的问题 - 确实如此,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-18
  • 2021-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-24
  • 1970-01-01
相关资源
最近更新 更多