多行grep没有列表

时间:2017-09-06 05:27:48

标签: 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" />
...

它用&#34; desc&#34;取出了行的值。在id中产生一个列表:

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

现在,生成数据文件的程序已将数据更改为如下所示:

<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>
...

我认为这可能更容易,因为我只需要在&gt;之间拉取值。和&lt;但如果我用这个:

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

但它没有正常工作。不确定我错过了什么。

4 个答案:

答案 0 :(得分: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=","}

    对于包含"desc的任何行,这会告诉awk打印变量c,然后是第三个字段。第三个字段是我们想要的数字。变量c最初是空字符串,但在第一次打印后,我们将其设置为逗号,。这会导致我们想要打印的数字,每个数字用逗号分隔。

  • END{print""}

    我们读完文件后,告诉awk打印换行符。

答案 1 :(得分: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:您需要打印换行符。

答案 2 :(得分: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>的属性id的{​​{1}}代码值,并将其作为数组"desc"的项目

检查第二个数组项值:

res

答案 3 :(得分:0)

desc\d+"><

之间的

grep 数字

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

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

-o用于捕获群组 -P告诉它是一个perl正则表达式 \K是一个后视断言,它告诉我们开始捕获数据 (?=)是一个先行断言,它告诉我们在找到<后停止捕获数据