我有一个像这样的大型.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;
答案 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)
当bash提供内置工具来完成所需的工作时,产生不必要的子shell只是简单的草率