【问题标题】:How to parse strings - detailed explanation and information on syntax如何解析字符串 - 语法的详细解释和信息
【发布时间】:2014-03-23 08:45:58
【问题描述】:

我想用一个简单的 1 行表达式解析 shell 脚本中的一组数据。但我不知道如何或在哪里可以找到任何描述它是如何完成的信息。我能找到的所有例子看起来都像是一个非法的数学方程式,我找不到任何描述它是如何工作的文档。

首先,这种解析形式到底是什么,所以我知道我在说什么以及要搜索什么。其次,我在哪里可以找到它的全部含义,这样我就可以学习如何正确使用它,而不仅仅是复制别人的作品而对其工作原理知之甚少。

/\.(\w+)/*.[0-9]/'s/" /"\n/g;s/=/\n/gp

我记得几十年前在 perl 中学习过这个,但早就忘记了它的含义。我花了几天时间寻找有关这一切意味着什么的信息。我能找到的只是具体的例子,没有解释它在技术上是什么以及它是如何工作的!

我想分离每个字段,然后在 shell 脚本中提取键名和数字数据。我意识到某些形式的解析在 shell 脚本中的完成方式与 php 或 perl 脚本不同。但我需要学习用于过滤掉我可以在 shell 和 php 中使用的特定数据集的解析语法。

目前我需要从 shell 脚本中的文件中解析一行数据,以获得其他支持脚本所需的一组条件。

#!/bin/sh
Line=`cat ./dump.txt`
#Line = "V:12.46 A:3.427 AV:6.08 D:57.32 S:LOAD CT:45.00 P:42.71 AH:2016.80"

# for each field parse data  ("/[A-Z]:[0-9]/}" < $Line)
# $val[$1] = $2

# $val["V"] = "12.46"
# $val["AV"] = "6.08"


if $val["V"] < 11.4
then
~/controls/stop.sh
else 
~/controls/start.sh
fi

if $val["AV"] > 10.7
then 
echo $val["AV"] > ./source.txt
else
echo "DOWN" > ./source.txt
fi

我需要识别并区分“V:”和“AV:”之间的区别。

在 php 中,我可以使用 foreach 并分解成一个数组。但是我厌倦了为一些可以在一行中完成的事情编写半页代码。我需要学习一种更简单、更有效的方法来解析字符串中的数据并将数据提取到可用变量中。

$Line = file_get_contents("./dump.txt");
$field = explode (' ' , $Line);
foreach($field as $arg)
{
$val = explode (':' , $arg);
$data[$val[0]] = $val[1];
}
# $data["V"] = "12.46"
# $data["AV"] = "6.08"

非常感谢一个快速的 shell 示例,但我真的需要知道“如何”自己做这个。请给我一些链接或搜索条件,以找到这些解析表达式的定义和语法。

提前感谢您的帮助。

【问题讨论】:

  • 所以你想把所有的 V 和 AV 放在一个单独的数组中?
  • 最好是单个数组,例如 $data["%"]。与该问题相关的主要问题是如何使用特定字符串解析的解析语法。我了解基础知识和结构,只是不记得 //*&+.[+m]/%% 解析语法。
  • 你能贴出要传递这些值的文件吗?
  • 这个脚本需要作为 4 个不同应用程序包的接口的一部分。它用于启动和停止控制各种硬件系统的外部模块控制器。输出文件由 python 脚本创建,该脚本用于其他用于控制电源负载控制器的直接硬件支持程序。我可以编写一个 php 脚本来完成所有的数据接口事务和 sighup 调用,但是在半页的 shell 脚本中完成相同的任务最终会花费好几页。

标签: php bash shell


【解决方案1】:

您所说的解析模式通常称为正则表达式或正则表达式。

对于 php,您可以从 http://au1.php.net/manual/en/book.pcre.php 找到很多有用的信息

正则表达式非常难,特别是对于复杂的表达式,所以我通常在谷歌上搜索在线正则表达式表达式测试器。最好突出显示匹配的内容。 Javascript 特别好,因为结果是即时的,并且正则表达式语法与 PHP 相同。

【讨论】:

  • 非常感谢。这正是我一直试图弄清楚的。现在我需要做更多的研究。
【解决方案2】:

特别感谢 James T 带领我朝着正确的方向前进。

通读正则表达式后,我找到了我需要的搜索模式。还包括一个简短的脚本来测试输出。考虑到 BASH 不能使用十进制数,我们需要将其转换为整数。十进制整数始终固定在 2 或 3 位,因此转换很容易,只需去掉小数即可。此外,记录字段的顺序保持不变,因此读取它们的顺序将保持不变。

适合搜索前 4 个字段的正则表达式是:

\w+:([0-9]+)\.([0-9]+)\s

( ) = the items to search/parse; using 2 searches for each data set "V:12.46"

\w = for the word search and the " + " means any 1 or more letters
: = for the delimiter
(  -search set 1:
  [0-9] = search any numbers and the " + " means any 1 or more digits
) -end search set 1
\. = for the decimal point in the data
(  -search set 2:
  [0-9] = search any numbers and the " + " means any 1 or more ( second set after the decimal)
) -end search set 2
\s = white space (blank space)

现在将前 3 个字段的搜索重复 3 次,给我 6 个变量。

\w+:([0-9]+)\.([0-9]+)\s\w+:([0-9]+)\.([0-9]+)\s\w+:([0-9]+)\.([0-9]+)\s

这是一个测试输出的简单脚本:

#!/bin/bash

Line="V:13.53 A:7.990 AV:13.65 D:100.00 S:BulkCharge CT:35.00 P:108.11 AH:2116.20"
regex="\w+:([0-9]+)\.([0-9]+)\s\w+:([0-9]+)\.([0-9]+)\s\w+:([0-9]+)\.([0-9]+)\s"

if [[ $Line =~ $regex ]]; then
        echo "match found in $Line"
        i=1
        n=${#BASH_REMATCH[*]}
        while [[ $i -lt $n ]]
        do
            echo "  capture[$i]: ${BASH_REMATCH[$i]}"
            let i++
        done
        Volt=${BASH_REMATCH[1]}${BASH_REMATCH[2]}
        Amp=${BASH_REMATCH[3]}${BASH_REMATCH[4]}
        AVG=${BASH_REMATCH[5]}${BASH_REMATCH[6]}
else
    echo "$Line does not match"
fi


if [ $Volt -gt 1200 ]
then
    echo "Voltage is $Volt"
fi

结果为:

match found in V:13.53 A:7.990 AV:13.65 D:100.00 S:BulkCharge CT:35.00 P:108.11 AH:2116.20
  capture[1]: 13
  capture[2]: 53
  capture[3]: 7
  capture[4]: 990
  capture[5]: 13
  capture[6]: 65
Voltage is 1353

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多