专家,
我在xml文件中有以下文本(文件中有20,000行)。
"21006041";"28006041";"34006211";"43";"101210-0001";101
以下是我需要每行的结果并附加到新文件的方法。
"
以下是我需要做的以获得上述结果。
<record record_no = "1" error_code="
BEGIN { FS=OFS=";" }
/<record/ {
gsub(/"/,"\"")
gsub(/'/,"")
gsub(/.*="|">.*/,"",$1)
$(NF+1)=$1;
$1="";
print $0;
}
这是我一直在尝试的。
foo
答案 0 :(得分:1)
这应该可以解决问题。
awk -F'">' -v OFS=';' '{gsub(/<record record_no = \"[0-9]+\" error_code="/,""); gsub(/"/,"\""); print $2,$1}'
策略是:
">
"
个xml实体替换为"
。使用以下数据生成脚本进行测试。该脚本将生成500x20000行文件,其中包含随机长度的记录,其中一些在值中带有破折号。
#!/bin/bash
recCount=0
for h in {1..500};
do
for i in {1..20000};
do
((recCount++))
error=$(( RANDOM % 998 + 1 ))
record="<record record_no = "'"'"${recCount}"'"'" error_code="'"'"${error}"'"'">"
upperBound=$(( RANDOM % 4 + 5 ))
for (( k=0; k<${upperBound}; k++ ));
do
randomVal=$(( RANDOM % 99999999 + 1))
record+=""${randomVal}"
if [[ $((RANDOM % 4)) == 0 ]];
then
randomVal=$(( RANDOM % 99999999 + 1))
record+="-${randomVal}"
fi
record+="""
if [[ $k != $(( ${upperBound} - 1 )) ]];
then
record+=";"
fi
done;
echo "${record}" >> "file-${h}.txt"
done;
done;
在我的笔记本电脑上,我获得了以下表现。
$ time cat file-*.txt | awk -F'">' -v OFS=';' '{gsub(/<record record_no = \"[0-9]+\" error_code="/,""); gsub(/"/,"\""); print $2,$1}' > result
real 0m18.985s
user 0m17.673s
sys 0m2.697s
作为额外的奖励,这里是sed中的“等效”命令:
sed -e 's|\("\)|"|g' -e 's|^.*error_code="\([^>]\+\)">\(.\+\).*$|\2;\1|g'
尽管策略相同,但速度要慢得多。使用了两个表达式。首先用"
替换所有"
xml实体。最后将>
之后的所有字符(。+)分组。以相反的顺序\2;\1
时间统计:
$ time cat file-* | sed -e 's|\("\)|"|g' -e 's|^.*error_code="\([^>]\+\)">\(.\+\).*$|\2;\1|g' > result.sed
real 5m59.576s
user 5m56.136s
sys 0m9.850s
答案 1 :(得分:0)
这太厚了:
$ awk -F""+" -v OFS='";"' -v dq='"' '{gsub(/^.*="|">$/,"",$1);print dq""$2,$4,$6,$8,$10dq";"$1}' test.in
"21006041";"28006041";"34006211";"43";"101210-0001";101