2017-09-06 23 views
1

我有一个grep行,其他人为我提供,我不知道如何改变。多行grep不制作列表

原始线是这样的:

grep id=\"desc\"* $ADDON_SETTINGS | awk -v ORS=, '{gsub(/"/, "");print $2}' | tr -s 'value=' ' ' | sed 's/ //g' | echo "[$(cat)]" 

它从包含一个文件的以下(这是一个样本段)被拉:

<settings> 
    <setting id="cfirst" value="false" /> 
    <setting id="cicons" value="false" /> 
    <setting id="days" value="3" /> 
    <setting id="delay" value="0.000000" /> 
    <setting id="desc01" value="10" /> 
    <setting id="desc02" value="18" /> 
    <setting id="desc03" value="6" /> 
    <setting id="desc04" value="13" /> 
    <setting id="desc05" value="6" /> 
... 

它拉出值用于与线在ID“递减”,并产生了一个清单:

10,18,6,13,6... 

现在,生成数据F程序ILE已更改的数据看起来像这样:

<settings version="2"> 
    <setting id="allc" default="true">false</setting> 
    <setting id="cfirst" default="true">false</setting> 
    <setting id="cicons" default="true">false</setting> 
    <setting id="days">3</setting> 
    <setting id="delay" default="true">0</setting> 
    <setting id="desc01">10</setting> 
    <setting id="desc02">18</setting> 
    <setting id="desc03">6</setting> 
    <setting id="desc04">13</setting> 
... 

我想我只需要拉之间>和<但值,这可能是更容易,如果我用这个:

grep id=\"desc\"* $ADDON_SETTINGS | awk -v ORS=, '{">|<";print $3}' | echo "[$(cat)]" 

但它的不正确。不知道我错过了什么。

回答

0

尝试:

$ awk -F'[<>]' '/"desc/{printf "%s%s",c,$3; c=","} END{print""}' file 
10,18,6,13 

工作原理:

  • -F'[<>]'

    这告诉AWK使用<>作为字段分隔。

  • /"desc/{printf "%s%s",c,$3; c=","}

    对于containst "desc任何线,这会告诉awk打印可变c接着第三个字段。第三个领域是我们想要的数字。变量c最初是空字符串,但在第一次打印后,我们将其设置为逗号,。这会导致我们想要打印的数字,每个数字都以逗号分隔。

  • END{print""}

    后,我们已经读完了文件,这会告诉awk将打印一个换行符。

0

您的解决方案不起作用的原因是'{">|<";print $3}',这是没有意义的。表达式">|<"不做任何事情。你想这样一行:

$ grep id=\"desc input.txt | awk -F"<|>" '{print $3}' 

然而,单一AWK的解决方案是:

awk 'match($0,/id=\"desc[0-9]+\">([0-9]+)/, a){printf "%s%s",sep,a[1];sep=","} END{print ""}' input.txt 
10,18,6,13 

或:与文件:

$ cat tst.awk 
match($0,/id=\"desc[0-9]+\">([0-9]+)/, a){ 
    printf "%s%s",sep,a[1];sep="," 
} 
END{print ""} 

$ awk -f tst.awk input.txt 
10,18,6,13 

说明:

  • 与正则表达式匹配id=\"desc[0-9]+\">([0-9]+)将括号中的数字放在[1]中。
  • 用分隔符sep打印一个[1],它第一次没有值。
  • END:您需要打印换行符。
0

您的内容有html/xml格式。
正确的方法是使用html/xml解析器。

xmlstarlet解决方案:

样品input.html内容:

<settings version="2"> 
    <setting id="allc" default="true">false</setting> 
    <setting id="cfirst" default="true">false</setting> 
    <setting id="cicons" default="true">false</setting> 
    <setting id="days">3</setting> 
    <setting id="delay" default="true">0</setting> 
    <setting id="desc01">10</setting> 
    <setting id="desc02">18</setting> 
    <setting id="desc03">6</setting> 
    <setting id="desc04">13</setting> 
</settings> 

的工作:

res=($(xmlstarlet sel -t -v "//setting[contains(@id, 'desc')]" 1.html | tr '\n' ' ')) 

这将提取<setting>标签值包含"desc"属性id,使这些项目的阵列res

检查第2个数组项值:

echo ${res[1]} 
18 
+0

这可能是最好的方式去作为文件是XML。我使用'xmlstarlet sel -t -v“/ settings/setting [contains(@id,'cicons')]”$ ADDON_SETTINGS'来计算常规设置,但我需要输出所有'“desc”用逗号隔开的行。因此,上面代码段的输出应该是'10,18,6,13' – edit4ever

+0

@ edit4ever,只需将'tr'\ n''''改为'tr'\ n'','期望的序列 – RomanPerekhrest

0

的grepdesc\d+"><

grep -oP 'desc\d+">\K\d+(?=<)' file | paste -sd "," 

之间的数字这将捕获desc\d+"><之间的数字。
注:desc\d+将解析desc01,desc02等

-o用于捕获组
-P告诉它是一个Perl的正则表达式
\K是向后断言它告诉开始捕获数据
(?=)是一个超前断言这里告诉停止捕获数据一次<被发现