论坛上的一位好伙伴帮助我创建了这个脚本,但我向它抛出的所有内容都输出错误,我不知道为什么或问题是什么。如果被询问为 bash test.sh,我在 ubuntu 的终端中运行了所有脚本。
我的目标是增加多个 .xml 文件的process></process>
标签,但某些文件可能有 1 到 100 个标签。
例子:
- jfksaJDFH
- <process>value=""</process>
- <process>value=""</process>
- <process>value=""</process>
- <process>value=""</process>
- jdhkjasdh
- <process>value=""</process>
- <process>value=""</process>
- <process>value=""</process>
- <process>value=""</process>
脚本之后:
- jfksaJDFH
- <process>value="1"</process>
- <process>value="2"</process>
- <process>value="3"</process>
- <process>value="4"</process>
- jdhkjasdh
- <process>value="5"</process>
- <process>value="6"</process>
- <process>value="7"</process>
- <process>value="8"</process>
脚本:
#!/bin/bash
dir="/mnt/Desktop/test/"
while IFS= read -r -d '' file
do
i=1
while IFS= read -r -u 3 line
do
if [[ $line = '<process></process>' ]]; then
echo "<process>value=\"$((i++))\"</process>"
else
echo "$line"
fi
done 3< "$file" > "$file.xml"
done < <(find $dir -type f -name \*.xml -print0)
当上面的脚本运行时删除最后一个<process>value=""</process>
将脚本修改为:
while IFS= read -r -d '' file
do
i=1
while IFS= read -r -u 3 line
do
if [[ $line = '<process></process>' ]]; then
echo "$line"
else
echo "<process>value=\"$((i++))\"</process>"
fi
done 3< "$file" > "$file.xml"
done < <(find $dir -type f -name \*.xml -print0)
文件的输出是这样的:
<process>value="1"</process>
<process>value="2"</process>
<process>value="3"</process>
<process>value="4"</process>
<process>value="5"</process>
<process>value="6"</process>
<process>value="7"</process>
<process>value="8"</process>
<process>value="9"</process>
<process>value="10"</process>
<process>value="11"</process>
<process>value="12"</process>
<process>value="13"</process>
<process>value="14"</process>
<process>value="15"</process>
<process>value="16"</process>
<process>value="17"</process>
<process>value="18"</process>
<process>value="19"</process>
<process>value="20"</process>
<process>value="21"</process>
<process>value="22"</process>
<process>value="23"</process>
换句话说,这会增加但会删除页面中的所有其他内容。
答案1
将此脚本放入文件中(例如:'increase.awk'):
BEGIN { i = 1 }
/.*<process>value=""<\/process>.*/ { split($0, a, "value=\"\"") ; print a[1] "value=\"" i++ "\"" a[2] ; next }
/.*/ { print $0 }
然后调用:
gawk -f increase.awk < yourinputfile
解释:在 awk 中,split("string", a, "separatorstring")
使用“separatorstring”作为分隔符,将“string”分割成一个名为 a 的数组。因此 a[1] 包含直到第一个“分隔符字符串”的所有内容,然后 a[2] 包含直到行尾或下一个“分隔符字符串”之前的所有内容,等等。
答案2
请不要这样做 XML。考虑一下您是否愿意 - XML 是一种主动忽略空格的结构化数据类型。具有一元标签,例如<attr name="fish" />
和其他东西,这意味着如果您使用正则表达式逐行解析它,有一天您的代码将神秘地崩溃。
执行此操作的方法是使用 XML 解析器。使用哪一个是个人喜好的问题,但我喜欢脚本编写XML::Twig
(perl 模块)。
要按照概述解决您的问题:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
sub increment_value {
my ( $twig, $process ) = @_;
my ($value) = ( $process->text =~ m/(\d+)/ );
print "Got $value\n";
if ( defined ( $value ) ) {
$process->set_text( 'value="' . ++$value . '"' );
}
else {
$process -> delete;
}
}
my $twig = XML::Twig->new(
'pretty_print' => 'indented',
'twig_handlers' => { 'process' => \&increment_value },
);
$twig->parsefile( 'your_file.xml' );
$twig->print; #prints to stdout.
这会触发每个元素的“处理程序” process
,用于提取、转换和替换文本。
答案3
您是否注意到,当您重写脚本时,您已经恢复了 if-then-else 构造的逻辑
请注意下面第 1 行和第 2 行注释行的位置。你在重写的代码中颠倒了它们
而 IFS= 读取 -r -d '' 文件 做 我=1 而 IFS= 读取 -r -u 3 行 做 如果 [[ $line = '' ]];然后 echo "value=\"$((i++))\"" # 第 1 行 **************** 别的 echo "$line" # 第 2 行 ************** 菲 完成 3“$file.xml” 完毕