2

我在 AIX 上,使用 bash,此时我们无法安装其他软件,因此我非常受限于命令行批处理和自定义 java 脚本。所以,我在不同的目录中有大量的 XML 文件。这是子集的样子。

root_dir
   Pages
      PAGES_1.XML
   Queries
      QUERIES_1.XML
      QUERIES_2.XML
      QUERIES_3.XML

我已经编写了一个脚本,它几乎可以满足我的所有需求,但是如果可能的话,我不知道如何在批处理脚本中完成最后一块拼图。我在根目录下创建一个新目录,将所有 XML 文件复制到新目录中,然后重命名它们以删除名称中的任何空格,并缓冲整数,以便它们可以按字母/数字顺序排序. 新输出如下所示:

copy_dir
    PAGES_001.XML
    QUERIES_001.XML
    QUERIES_002.XML
    QUERIES_003.XML

我快到了。最后一点是这些单独的XML文件需要针对每种类型组合成一个XML文件,所以HISTORY_001.XML到HISTORY_099.XML需要组合,然后QUERIES_001.XML到QUERIES_099.XML需要组合,但是只有在文件中的特定点。我有一个用于选择我想要的部分的文件的正则表达式,现在我只需要弄清楚如何循环遍历每个文件子集。也许我跳了枪,应该在移动它们之前做,但是假设它们都在一个目录中,我该怎么做呢?

这是数据的示例。所有 XML 文件都携带这些相同类型的信息。

页面

<?xml version="1.0"?>
<project name="">
  <rundate></rundate>
  <object_type code="false" firstitem="1" id="5" items="65" name="Pages">
    <primary_key>Page Name</primary_key>
    <secondary_key>Language Code</secondary_key>
    <secondary_key>Page Field ID</secondary_key>
    <secondary_key>Field Type</secondary_key>
    <secondary_key>Record (Table) Name</secondary_key>
    <secondary_key>Field Name</secondary_key>
    <item id="ACCTG_TEMPLATE_AP">
      ...
    </item>
    <item id="ACCTG_TEMPLATE_AR">
      ...
    </item>
  </object_type>
</project>

查询

<?xml version="1.0"?>
<project name="">
  <rundate></rundate>
  <object_type code="false" firstitem="1" id="10" items="46" name="Queries">
    <primary_key>Query Name</primary_key>
    <primary_key>User ID</primary_key>
    <item id="1099G_ALL_SHORT. ">
      ...
    </item>
    <item id="1099G_ALL_VOUCHERS. ">
      ...
    </item>
  </object_type>
</project>

正则表达式拉出标题

(?:(?!(^\s*i<item)).)*

正则表达式提取细节

^(\s*<item id=).*(</item>)

正则表达式拉出页脚

^(\s*</object_type).*

所以我假设我想要做的事情有一个计数器,循环遍历每个对象类型 XML 子集,如果我是第一个循环然后拉标题和细节并输出到一个新的摘要文件,然后继续所有其他文件到连接细节,然后如果最后一个文件或更改为新的对象类型,则也输出页脚。您认为使用 bash 脚本可以做到这一点吗?

4

2 回答 2

0
combine()
{
    # pull the header from 1st file
    while IFS= read && word=($REPLY) && [ "$word" != "<item" ]
    do  echo "$REPLY"
    done <$1

    # concat the detail from all files
    for file
    do  cmd=:
        while IFS= read && word=($REPLY)
        do  case $word in \<item) cmd=echo;; esac
            $cmd "$REPLY"
            case $word in \</item\>) cmd=:;; esac
        done <$file
    done

    # output the footer
    while IFS= read && word=($REPLY)
    do  case $word in \</object_type\>) cmd=echo;; esac
        $cmd "$REPLY"
    done <$file
}

combine PAGES_???.XML >PAGES.XML
combine QUERIES_???.XML >QUERIES.XML
于 2013-10-29T11:00:52.047 回答
0

first这将吐出命令来进行排序和分类,只需提供函数/脚本/对, middle,last或组中的文件执行正确操作的任何内容 onlyfirstandmiddle命令必须处理空参数列表,middle对于二元素组和first没有1-sequenced 文件的组。

编辑:我将 seds 分解为每行一个命令来处理不喜欢分号的 seds

运行这个例如sh this.sh *_*.*

#!/bin/sh
#
# spit commands to sort, group, and classify argument filenames 
# sorting by the number between `_` and `.` in their names and 
# grouping by the text before the _.
{
# Everything through the sort would just be `ls -v` on GNU/anything...
for f; do
    pfx=${f%%_*}
    tail=${f#*_}
    sortable=`printf %s_%03d.%s $pfx ${tail%.*} ${tail##*.}`
    [ $f != $sortable ] \
      && echo  mv $f $sortable >&2
    echo $sortable
done \
| sort \
| sed '
    /_0*1\./! H
    // {
       x
       1! {
          y/\n/ /
          p
       }
    }
    $!d
    x
    y/\n/ /
' \
| sed '
    s/\([^ ]*\)\(.*\) \(.*\)/first \1\nmiddle\2\nlast \3/
    t
    s/^/only /
'
} 2>&1

上面sed的第一个 s 累积了可以通过它们的第一行识别的每行一个单词的组。第二个在正确的命令中对组和子进行分类。它们是分开的,因为第一个 sed 涉及一个双泵来处理寡妇组,而且它们本身就足够多毛。

于 2013-09-24T20:12:38.603 回答