sed使用bash变量删除两行之间的不匹配行

时间:2016-06-29 10:03:04

标签: bash sed

我需要帮助理解sed,bash和while循环的奇怪问题。

我的数据如下:

- 文件1- CSV account,hostnames,status,ipaddress,port,user,pass

-File 2- XML - 这是一个帐户下两个条目的样本记录集

<accountname="account">

<cname="fqdn or simple name goes here">
<field="hostname">ahostname or ipv4 goes here</field>
<protocol>aprotocol</protocol>
<field="port">aportnumber</field>
<field="username">ausername</field>
<field="password">apassword</field>
</cname>

<cname="fqdn or simple name goes here">
<field="hostname">ahostname or ipv4 goes here</field>
<protocol>aprotocol</protocol>
<field="port">aportnumber</field>
<field="username">ausername</field>
<field="password">apassword</field>
</cname>

</accountname>

到目前为止,我可以在File1到File2的相应帐户持有者之间添加记录。但是,如果我需要删除不再存在的记录,它就无法有效地工作,因为它擦除了来自不同帐户的其他记录,即它不会在匹配的帐户名之间删除。

我在我的bash程序中使用while循环从文件1导入到文件2中:

-Bash Program excerpts-
//Read File in to F//
cat File 2 | while read F
do

//extract fields from F into variables
_vmname="$(echo $F |grep 'cname'| sed 's/<cname="//g' |sed 's/.\{2\}$//g')"
_account="$(echo $F | grep 'accountname' | sed 's/accountname="//g' |sed 's/.\{2\}$//g')"

  //  I then compare my File1 and look for stale records that are still in File2

        if grep "$_vmname" File1 ;then
                continue
        else
// if not matched, delete between the respective accountname

sed -i '/'"$_account"'/,/<\/accountname>/ {/'"$_vmname"'/,/<\/cname>/d}' File2

如果我手动声明_vmname和_account并运行

sed -i '/'"$_account"'/,/<\/accountname>/ {/'"$_vmname"'/,/<\/cname>/d}' File2

它从File2中删除过时的记录。当我让我的bash脚本运行时,它没有。

我认为我有三个问题:

  1. 在循环内读取_vmname和_account名称的变量会使其多次读取。任何更好的方法都值得赞赏。
  2. 我不认为用于匹配这两个模式的sed语句然后删除就像我想要在while循环中一样。
  3. 我的思想链可能存在逻辑问题。
  4. 任何指针,请不要使用awk,perl,lxml或python。

    谢谢!

1 个答案:

答案 0 :(得分:0)

  

请不要awk

我很欣赏你想要保持简单,我认为awk似乎比你正在做的更复杂。但是我想指出你到目前为止在文件中有3个grep和4个sed调用每行,以处理另一个文件 N 次,每行一次。那个 O(mn)使用地球上最慢的方法来读取文件(while循环)。它没有用。

  

我的思维链可能存在逻辑问题。

我担心我们必须考虑到这种可能性!

正确的建议是使用XML解析器处理XML,因为XML不是常规语言,因此无法使用正则表达式进行解析。这就是真正你需要的东西,因为你的程序处理整个XML文档。您不只是根据偶然的格式化工件取出位数;你想要添加那些不存在的记录,并删除那些不再存在的记录&#34;。显然,您需要保留XML文档中的信息,否则您只需从CSV生成它。解析器会用勺子喂它给你。

第二好的建议是使用awk。我想你可能会尝试一种方法:

  1. 处理CSV并生成要插入的XML。
  2. 在awk中,首先将新输入XML读入由cname键入的数组中,然后处理XML目标一次。对于每个CNAME,请咨询您的阵列;如果找到匹配项,请插入预先构建的XML替换项(或相应地修改&#34;段&#34;)。
  3. 我不确定删除条件是什么,因此我不知道是否可以通过步骤#2在同一个传递中完成。如果没有,以某种方式提取显着信息。也许打印两个文件中的每个文件的密钥列表,并使用comm(1)生成一个待删除的列表。然后,类似于步骤#2,读入该列表,并再次处理XML文件。将您删除的任何内容写入stderr,以便跟踪丢失的内容,从哪些行开始。
  4.   

    任何指针

    每当您发现自己为N个输入处理相同的文件N次时,您就知道自己已经陷入困境了。两个输入中的一个总是较小,并且可以放入某种数组。 cat file | while read是另一个警告信号,告诉你使用awk 或任何十分明显的实用程序来理解文本行。

    两周前你在SO上发布了你的问题。我怀疑没有人回答,因为你警告他们:先发制人地说,实际上,不要告诉我使用好的工具。我只是在这里建议你脱下那件紧身衣后会更舒服。在这种情况下,更好的工具是唯一正确的答案。