如何在BASH中获取该列?

时间:2015-10-22 08:09:23

标签: bash awk sed

我有一个像这样的大型.xml文件:

c1="a1" c2="b1" c3="cccc1"

c1="aa2" c2="bbbb2" c3="cc2"

c1="aaaaaa3" c2="bb3" c3="cc3"

...

我需要如下结果:

a1 b1 cccc1

aa2 bbbb2 cc2

aaaaaa3 bb3 cc3

...

如何在BASH中获取该列?

我在PL / SQL中有以下方法,但它非常不方便:

SELECT C1,
       TRIM(BOTH '"' FROM REGEXP_SUBSTR(C1, '"[^"]+"', 1, 1)) c1,
       TRIM(BOTH '"' FROM REGEXP_SUBSTR(C1, '"[^"]+"', 1, 2)) c2,
       TRIM(BOTH '"' FROM REGEXP_SUBSTR(C1, '"[^"]+"', 1, 3)) c3
FROM TEST;

3 个答案:

答案 0 :(得分:1)

awk -F '"' '{ for(i=2; i<=NF; i+=2) { printf $i" " } print "" }'

说明

-F '"'使得Awk将引号(")视为字段分隔符。例如,Awk将分割线......

c1="a1" c2="b1" c3="cccc1"

...进入编号为......

的字段
1: 'c1='
2: 'a1'
3: ' c2='
4: 'b1'
5: ' c3='
6: 'cccc1'
7: ''

for(i=2; i<=NF; i+=2) { printf $i" " }从字段2开始,打印字段的值,跳过字段,然后继续。在这种情况下,将打印字段2,4和6。

print输出后跟换行符的字符串。 printf也输出一个字符串,但不附加换行符。因此...

printf $i" "

...输出字段$i后跟空格的值。

print ""

...只是输出换行符。

答案 1 :(得分:1)

您还可以查看内置的子串替换/删除 bash优惠。在短脚本或 One-Liner

#!/bin/bash

while read -r line; do 
    new=${line//c[0-9]=/}  ## remove 'cX=', where X is '0-9'
    new=${new//\"/}        ## remove all '"' (double-quotes)
    echo "$new"
done <"$1"

exit 0

<强>输入

$ cat dat/stuff.xml
c1="a1" c2="b1" c3="cccc1"

c1="aa2" c2="bbbb2" c3="cc2"

c1="aaaaaa3" c2="bb3" c3="cc3"

<强>输出

$ bash parsexmlcx.sh dat/stuff.xml
a1 b1 cccc1

aa2 bbbb2 cc2

aaaaaa3 bb3 cc3

作为One-Liner

while read -r line; do new=${line//c[0-9]=/}; new=${new//\"/}; echo "$new"; done <dat/stuff.xml

答案 2 :(得分:1)

使用cut

cut -d'"' -f2,4,6 --output-delimiter=" " test.txt

如果列数不知道,您可以使用sed:

sed 's/[a-z][a-z0-9]\+="\([^"]\+\)"/\1/g' < test.txt

<强>解释

  • [a-z][a-z0-9]\+ - 匹配以alpha字符开头的字符串,后跟任意数量的字母数字字符
  • "\([^"]\+\)" - 捕获引号内的任何字符串
  • \1 - 表示捕获的字符串,在本例中用于替换整个匹配

perl方法(基于awk answer by @A-Ray

perl -F'"' -ane 'print join(" ",@F[ map { 2 * $_ + 1} (0 .. $#F) ]),"\n";' < test.txt

<强>解释

  • -F'"'将输入分隔符设置为"
  • -a自动启动 - 这导致@F被归档输入中的字段内容
  • -n遍历所有行,但默认情况下不打印
  • -e执行以下代码
  • map { 2 * $_ + 1} (0 .. $#F)生成索引列表(1,3,5 ...)
  • @F[map { 2 * $_ + 1} (0 .. $#F)]从数组中获取切片,仅选择奇数字段
  • join - 用空格连接切片

注意:我没有充分的理由不使用这种方法,前两个更容易。

一些基准测试(在Raspberry Pi上,60000行输入文件和输出丢弃到/ dev / null)

  • cut - 0m0.135s毫不奇怪
  • sed - 0m5.864s
  • perl - 0m8.218s - 我想重新生成索引列表的每一行都不是那么快(使用硬编码的切片列表,它会变为一半,但这样做会失败)
  • bash purist“solution” - 0m52.027s谈论
  

当bash提供内置工具来完成所需的工作时,产生不必要的子shell只是简单的草率