【问题标题】:sed / awk complex line replacementsed/awk 复杂行替换
【发布时间】:2020-10-29 20:40:32
【问题描述】:

我想像这样替换数千行,但我很难让它工作,而且我有 2 个变量 $time 和 $date 条件,不能使其成为全局变量。:

示例:<!-- 2020-07-06 16:45:00 WEST / 1594050300 --> <row><v>5.0000000000e+00</v></row>

替换:<!-- 2020-07-06 16:45:00 WEST / 1594050300 --> <row><v>NaN</v></row>

我用 sed 试过了:

sed -i '<!-- 2020-07-06 16:45:00 WEST \/ 1594050300 --> <row><v>5.0000000000e+00<\/v><\/row>.*/<!-- 2020-07-06 16:45:00 WEST \/ 1594050300 --> <row><v>NaN<\/v><\/row>/' dump_teste.xml

sed:-e 表达式#1,字符 1:未知命令:`

还有 awk:

awk '{gsub(/<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>1.9933333333e+00</v></row>/,"<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>NaN</v></row>")}1' tmp.txt
    awk: cmd. line:1: {gsub(/<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>1.9933333333e+00</v></row>/,"<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>NaN</v></row>")}1
    awk: cmd. line:1:                                                     ^ syntax error
    awk: cmd. line:1: {gsub(/<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>1.9933333333e+00</v></row>/,"<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>NaN</v></row>")}1
    awk: cmd. line:1:                                                                               ^ syntax error
    awk: cmd. line:1: {gsub(/<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>1.9933333333e+00</v></row>/,"<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>NaN</v></row>")}1
    awk: cmd. line:1:                                                                                                                                         ^ syntax error
    awk: cmd. line:1: {gsub(/<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>1.9933333333e+00</v></row>/,"<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>NaN</v></row>")}1
    awk: cmd. line:1:                                                                                                                                                      ^ syntax error
    awk: cmd. line:1: {gsub(/<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>1.9933333333e+00</v></row>/,"<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>NaN</v></row>")}1
    awk: cmd. line:1:                                                                                                                                                                ^ unterminated string
    awk: cmd. line:1: {gsub(/<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>1.9933333333e+00</v></row>/,"<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>NaN</v></row>")}1
    awk: cmd. line:1:                                                                                                                                                                ^ syntax error

awk '{sub(/<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>1.9933333333e+00</v></row>/,"<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>NaN</v></row>")}1' tmp.txt
awk: cmd. line:1: {sub(/<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>1.9933333333e+00</v></row>/,"<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>NaN</v></row>")}1
awk: cmd. line:1:                                                    ^ syntax error
awk: cmd. line:1: {sub(/<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>1.9933333333e+00</v></row>/,"<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>NaN</v></row>")}1
awk: cmd. line:1:                                                                              ^ syntax error
awk: cmd. line:1: {sub(/<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>1.9933333333e+00</v></row>/,"<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>NaN</v></row>")}1
awk: cmd. line:1:                                                                                                                                        ^ syntax error
awk: cmd. line:1: {sub(/<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>1.9933333333e+00</v></row>/,"<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>NaN</v></row>")}1
awk: cmd. line:1:                                                                                                                                                     ^ syntax error
awk: cmd. line:1: {sub(/<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>1.9933333333e+00</v></row>/,"<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>NaN</v></row>")}1
awk: cmd. line:1:                                                                                                                                                               ^ unterminated string
awk: cmd. line:1: {sub(/<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>1.9933333333e+00</v></row>/,"<!-- 2020-07-08 12:00:00 WEST / 1594206000 --> <row><v>NaN</v></row>")}1
awk: cmd. line:1:                                                                                                                                                               ^ syntax error

【问题讨论】:

  • 你需要一个 xml 解析器。
  • sed -E 's/&lt;v&gt;([^&lt;]*)/&lt;v&gt;NaN/g' 呢?
  • 是一个不错的选择,但我有 2 个变量要在 $date 和 $time 之前传递,在我想要更改的具体行中,而不是在文件的所有 100 万行中:)
  • 那么sed -E '/2020-07-06 16:45:00/s/&lt;v&gt;([^&lt;]*)/&lt;v&gt;NaN/g' ?

标签: xml bash awk sed


【解决方案1】:

您正在尝试的命令没有 s 选项,这就是它给出错误的原因。

sed -i 's/<!-- 2020-07-06 16:45:00 WEST \/ 1594050300 --> <row><v>5.0000000000e+00<\/v><\/row>.*/<!-- 2020-07-06 16:45:00 WEST \/ 1594050300 --> <row><v>NaN<\/v><\/row>/g' dumpteste.xml

sed -i 's/<v>.*<\/v>/<v>NAN<\/v>/g' dumpteste.xml

您有两个变量 $date 和 $time 并且想要匹配具有这些变量的行,然后应用 sed。执行以下操作:

sed "/"$date" "$time" .*<\/row>/ s/<v>.*<\/v>/<v>NAN<\/v>/g" dumpteste.xml

在上面的命令中如果行是

<!-- 2020-07-06 16:45:00 WEST / 1594050300 --> <row><v>5.0000000000e+00</v></row>```
And date and time variable are
date='2020-07-06' time='16:45:00' 
then only line containg that date and time will be edited by sed.


Did it solved your problem?

【讨论】:

  • 差不多,它适用于特定的 $date 和 $time。
  • 如果我有以下情况:time_from='16:45:00' time_till='17:45:00' date='2020-07-06' 仍然可以使用 sed?
  • 感谢您的所有努力!
  • 来自原始问题:“我有 2 个变量 $time 和 $date”,时间是什么时候分成一个范围的?请不要在回答后更改问题。以后提到它时会让人感到困惑。
  • 根据您满足范围和变量的需求,请参阅我在下面给出的另一个答案
【解决方案2】:

根据您的需要,下面是一个将文件中的数字替换为 NAN 的命令,考虑到所有在时间范围内的行,无论行出现的顺序如何。

set date from and till variables and then below command

while IFS= read -r in; do out="$(echo "$in" | awk '{print $2}')" && outtime="$(echo "$in" | awk '{print $3}')" && sed -i "/"$out" "$outtime"/ s/<v>.*<\/v>/<v>NAN<\/v>/" dumpteste.xml; done <<< "$(sort -k3 -k4 -k5 dumpteste.xml | awk -v date="$date" -v from="$from" -v till="$till" '$2 == date && $3 >= from && $3 <= till' | tac)"

上述命令示例

cat dumpteste.xml         #original file
<!-- 2020-07-06 16:45:00 WEST / 1594050300 --> <row><v>5.0000000000e+00</v></row>
<!-- 2020-07-06 16:47:00 WEST / 1594050300 --> <row><v>5.0000000000e+00</v></row>
<!-- 2020-07-06 17:47:00 WEST / 1594050300 --> <row><v>5.0000000000e+00</v></row>
<!-- 2020-07-06 16:45:00 WEST / 1594050300 --> <row><v>5.0000000000e+00</v></row>
<!-- 2020-07-06 16:48:00 WEST / 1594050300 --> <row><v>5.0000000000e+00</v></row>
<!-- 2020-07-06 17:45:00 WEST / 1594050300 --><row<v>5.0000000000e+00</v></row>
<!-- 2020-08-06 16:45:00 WEST / 1594050300 --> <row><v>5.0000000000e+00</v></row>



date=2020-07-06
from=16:45:00
till=17:45:00
 Output  
cat dumpteste.xml      #after change

<!-- 2020-07-06 16:45:00 WEST / 1594050300 --> <row><v>NAN</v></row>
<!-- 2020-07-06 16:47:00 WEST / 1594050300 --> <row><v>NAN</v></row>
<!-- 2020-07-06 17:47:00 WEST / 1594050300 --> <row><v>5.0000000000e+00</v></row>
<!-- 2020-07-06 16:45:00 WEST / 1594050300 --> <row><v>NAN</v></row>
<!-- 2020-07-06 16:48:00 WEST / 1594050300 --> <row><v>NAN</v></row>
<!-- 2020-07-06 17:45:00 WEST / 1594050300 --> <row><v>NAN</v></row>
<!-- 2020-08-06 16:45:00 WEST / 1594050300 --> <row><v>5.0000000000e+00</v></row>

请参阅日期 2020-07-06,当提供时间范围 16:45:00-17:45:00 时,时间 16:45、16:48、16:47、17:45 的行已更改。 对于时间 16:45 但日期 2020-08-06 它没有更改,因为日期不匹配。

此外,如果您需要在范围内输入日期,请​​定义四个变量:日期、结束日期、开始日期、截止日期。并执行以下命令

date=2020-07-06
enddate=2020-08-06
from=16:45:00
till=17:45:00
while IFS= read -r in; do out="$(echo "$in" | awk '{print $2}')" && outtime="$(echo "$in" | awk '{print $3}')" && sed -i "/"$out" "$outtime"/ s/<v>.*<\/v>/<v>NAN<\/v>/" du*; done <<< "$(sort -k3 -k4 -k5 du* | awk -v date="$date" -v from="$from" -v till="$till" -v enddate="$enddate" '$2 >= date && $2 <= enddate && $3 >= from && $3 <= till' | tac)"

以上命令将帮助您更改在范围内提供日期和时间的值 希望这就够了吗?

短版: 1)。有时间范围

date=2020-07-06 && from=16:45:00 && till=17:45:00 && gawk -i inplace -v date="$date" -v from="$from" -v till="$till" '$2 == date && $3 >= from && $3 <= till {gsub(/<v>[^<]*/, "<v>nan<")}1' dumpteste.xml

2)。具有日期和时间范围

date=2020-07-06 && from=16:45:00 && till=17:45:00 && enddate=2020-08-06 && awk -v date="$date" -v from="$from" -v till="$till" -v enddate="$enddate" '$2 >= date && $2 <= enddate && $3 >= from && $3 <= till {gsub(/<v>[^<]*/, "<v>nan<")}1' dumpteste.xml

【讨论】:

  • 我添加了另一个命令来回答,它使用范围内的日期和范围内的时间。如果您发现它有用,请点击答案左侧的复选图标以接受它
猜你喜欢
  • 2016-10-29
  • 2011-01-23
  • 1970-01-01
  • 2013-05-30
  • 2021-07-06
  • 1970-01-01
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多