关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » HTML5 »如何用Shell脚本生成XML文件

    如何用Shell脚本生成XML文件

    2015-03-14 00:00:00 出处:linux.cn
    分享

    微信扫一扫:分享

    Scan me!

    微信里点“发现”,扫一下

    二维码便可将本文分享至朋友圈。

    今天把这段时间学习完shell后完成工作上的一个小案件整理了一下,分享给大家!

    说来也巧了,作为一个刚刚毕业半年的菜鸟,进入公司后,听公司的大牛推荐学习linux–”鸟哥的私房菜“,基本上是从去年8月份开始到了今年的1月份,基本上是把基础篇看完了,开始了解shell脚本的相关知识。刚好公司有了一个shell脚本的案件给我了,时间上也没有多紧。然后就一边学习一边开始做,虽然中途客户反映先前的业务逻辑有问题耽搁了两周,但总算是到最后完成了,自己学习的东西能用到很开心,今天闲了,把代码整理了一下,分享给大家

    具体是这样:

    要求是写一个shell脚本,安装要求查询数据,将符合条件的数据按照客户给定的xml样式进行组装,然后加入到crontab中,定时执行通过scp或者ftp放到客户服务器上。

    具体实现步骤:

    一、编写生成xml文档的代码

    网上搜索了一篇博客:http://blog.csdn.net/dengzhaoqun/article/details/7262271 拿来学习了一下,感觉好用,自己就根据自己的实际情况修改了一下:

    #! /bin/bash
    # filename: create_xml.sh
    # create_wangxb_20150123
    #
    # 从外部传入的第一个参数作为xml的文件名
    outfile=$1
    # xml中的缩进位
    tabs=0
    
    # ++++++++++++++++++++++++++++
    # 组装一个节点,输出到文件
    # 说一说传参数时的这几个区别:假如有下面这个脚本执行的命令
    # /path/to/scriptname  opt1  opt2  opt3  opt4 
    # $0: 的值是默认是脚本的名字,从$1-$4 开始就是参数的值
    # $# :代表后接的参数『个数』
    # $@ :代表『 "$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来); 
    # $* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 "$1 $2 $3 $4" 』之意。
    # 在shell中我们可以也可以使用${}包含变量名,来调用变量
    # ++++++++++++++++++++++++++++
    put(){
        echo '<'${*}'>' >> $outfile
    }
    
    # 这里也是输出一个xml的节点,只是比上面的节点有更多的设置
    # ${@:2} 的意思:它的值就是由第二个参数开始到最后一个参数,为什么要这样?有时可能你的第二个参数中有空格,shell接受参数是以空格计算的
    put_tag() {
        echo '<'$1'>'${@:2}'</'$1'>' >> $outfile
    }
    # 同样是一个输出节点函数,但是添加了CDATA,防止特殊字符造成xml解析失败
    put_tag_cdata() {
        echo '<'$1'><![CDATA['${@:2}']]></'$1'>' >> $outfile
    }
    
    put_head(){
        put ' '${1}' '
    }
    # 这是一个缩进的算法,自行理解
    out_tabs(){
        tmp=0
        tabsstr=""
        while [ $tmp -lt $((tabs)) ]
        do
            tabsstr=${tabsstr}'t'
            tmp=$((tmp+1))
        done
        echo -e -n $tabsstr >> $outfile
    }
    
    tag_start(){
        out_tabs
        put $1
        tabs=$((tabs+1))
    }
    
    tag() {
        out_tabs
        if [ "$1" == 0 ]
        then
            put_tag $2 $(echo ${@:3})
        elif [ "$1" == 1 ]
        then
            put_tag_cdata $2 $(echo ${@:3})
        fi
    }
    
    tag_end(){
        tabs=$((tabs-1))
        out_tabs
        put '/'${1}
    }

    这里有一些基础知识:

    关于参数:

    假如有下面这个脚本执行的命令
    /path/to/scriptname opt1 opt2 opt3 opt4

     $0: 的值是默认是脚本的名字,从$1-$4 开始就是参数的值
     $# :代表后接的参数『个数』
     $@ :代表『 "$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来); 
     $* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 "$1 $2 $3 $4" 』之意。
     在shell中我们可以也可以使用${}包含变量名,来调用变量

    关于 ${@:2} 这种形式的说明,我转载了一篇博客:http://www.cnblogs.com/wxb0328/p/4276751.html

    二、从数据库查数据利用上面的函数,制作xml文件

    #!/bin/bash
    # filename: ts_xml.sh
    # create_wangxb_20150126
    #
    
    PATH=/u01/app/oracle/product/10.2.0/db_1/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/opt/dell/srvadmin/bin:/home/p3s_batch/tools:/home/p3s_batch/bin
    export PATH
    # Database account information file
    source ~/.p3src
    
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    # set some variable 
    # XMLSCRIPT: 脚本的绝对路径
    # MATCHING_RESULT_XML: xml_1的文件名 
    # XML_FUNC_FILE: 生成xml函数文件路径
    # MATCHING_RESULT_QUERY_DATA: sqlplus 查出数据保存的零时文件
    # MATCHING_RESULT_QUERY_SQL: sqlplus 查询的sql语句
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    # 下面是一些基础的设置
    export XMLSCRIPT=/usr/p3s/batch/jaaa_match/tmp_xa_wangxb
    XML_DIR="$XMLSCRIPT/xmldata"
    XML_FUNC_FILE="xml_func.sh"
    
    MATCHING_RESULT_XML="matching_result_"$(date '+%Y%m%d_%H%M%S')".xml"
    MATCHING_RESULT_QUERY_DATA="matching_result_query_data.tmp"
    MATCHING_RESULT_QUERY_SQL="matching_result_query.sql"
    
    CLIENT_LIST_XML="client_list_"$(date '+%Y%m%d_%H%M%S')".xml"
    CLIENT_LIST_QUERY_DATA="client_list_query_data.tmp"
    CLIENT_LIST_QUERY_SQL="client_list_query.sql"
    
    # add_wangxb_20150225
    if [ ! -d "$XML_DIR" ];
    then
        mkdir $XML_DIR
    fi
    
    #+++++++++++++++++++++++++++
    # modify_wangxb_20150224
    # check for temporary file 
    #+++++++++++++++++++++++++++
    if [ -e "$XML_DIR/$MATCHING_RESULT_XML" ];
    then
        rm -f $XML_DIR/$MATCHING_RESULT_XML
    fi
    
    if [ -e "$XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA" ];
    then
        MATCHING_RESULT_QUERY_DATA="matching_result_query_data_"$(date '+%Y%m%d%H%M%S')".tmp"
    fi
    #+++++++++++++++++++++++++++++++++++++++++++++++++
    # add_wangxb_20150225
    # check system time,  choice query time period
    # 这是是根据crontab每天执行的时间,取得我们查询数据库时的where条件的时间区间
    #+++++++++++++++++++++++++++++++++++++++++++++++++
    sys_datetime=$(date '+%Y%m%d%H')
    first_chk_datetime="$(date '+%Y%m%d')04"
    second_chk_datetime="$(date '+%Y%m%d')12"
    third_chk_datetime="$(date '+%Y%m%d')20"
    # 由于服务器crontab是上面的时间,但是执行的shell比较多,在调用我这个shell的时候,不一定就是04:30 ,12:30, 20:30所以,这里的根据系统的时间判断时 范围给的比较宽
    case $sys_datetime in
        "$first_chk_datetime"|"$(date '+%Y%m%d')05"|"$(date '+%Y%m%d')06"|"$(date '+%Y%m%d')07")
            chk_start=$(date '+%Y-%m-%d 21:00:00' -d '-1 day')
            chk_end=$(date '+%Y-%m-%d 04:29:59')
        ;;
        "$second_chk_datetime"|"$(date '+%Y%m%d')13"|"$(date '+%Y%m%d')14"|"$(date '+%Y%m%d')15")
            chk_start=$(date '+%Y-%m-%d 04:30:00')
            chk_end=$(date '+%Y-%m-%d 12:29:59')
    
        ;;
        "$third_chk_datetime"|"$(date '+%Y%m%d')21"|"$(date '+%Y%m%d')22"|"$(date '+%Y%m%d')23")
            chk_start=$(date '+%Y-%m-%d 12:30:00')
            chk_end=$(date '+%Y-%m-%d 20:59:59')
    
        ;;
        *)
            chk_start=$(date '+%Y-%m-%d 00:00:00')
            chk_end=$(date '+%Y-%m-%d 23:59:59')
    
        ;;
    esac
    
    # modify_wangxb_20150310
    # 下面的是做一个oracle数据库连接的测试,假如连接失败,后续代码不再执行,并且写入错误日志
    $ORACLE_HOME/bin/sqlplus -s $ORAUSER_WEB_PASDB << EOF
    set echo off
    set feedback off
    alter session set nls_date_format='YYYY-MM-DD:HH24:MI:SS';
    select sysdate from dual;
    quit
    EOF
    if [ $  -ne 0 ]
    then 
        echo "********** DBへのリンク己窃した **********"
        exit
    else
        echo "********** DBへのリンクOKです **********"
    fi
    # sqlplus就是oracle的一个客户端软件,具体使用方法可以问度娘,这里传入要执行的sql和参数,将结果 > 输出到指定文件
    $ORACLE_HOME/bin/sqlplus -s $ORAUSER_WEB_PASDB @$XMLSCRIPT/$MATCHING_RESULT_QUERY_SQL "$chk_start" "$chk_end" > $XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA
    
    # create matching result's xml file
    # add_wangxb_20150227
    # 下面的算法就是将查出的数据进行分析,调用xml函数生成xml文件
    source "$XMLSCRIPT/$XML_FUNC_FILE" "$XML_DIR/$MATCHING_RESULT_XML"
    put_head 'xml version="1.0" encoding="utf-8"'
    tag_start 'ROOT'
    if [ -s "$XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA" ];
    then
        datas=${XMLSCRIPT}/${MATCHING_RESULT_QUERY_DATA}
        #for res in $datas
        while read res;
        do
            stock_id=$(echo $res | awk 'BEGIN {FS="\^\*\^"} {print $1}')
            seirino=$(echo $res | awk 'BEGIN {FS="\^\*\^"} {print $2}')
            match_flg=$(echo $res | awk 'BEGIN {FS="\^\*\^"} {print $3}')
            unmatch_riyuu=$(echo $res | awk 'BEGIN {FS="\^\*\^"} {print $4}')
            up_date_tmp=$(echo $res | awk 'BEGIN {FS="\^\*\^"} {print $5}')
            up_date=$(echo $up_date_tmp | awk 'BEGIN {FS="@"} {print $1 " " $2}')
            tag_start 'MATCHING'
            tag 0 'STOCKID' ${stock_id:-""}
            tag 0 'SEIRINO' ${seirino:-""}
            tag 0 'RESULT' ${match_flg:-""}
            tag 1 'REASON' ${unmatch_riyuu:-""}
            tag 0 'UPDATE_DATE' ${up_date:-""}
            tag_end 'MATCHING'
        done < $datas
    fi
    tag_end 'ROOT'
    rm $XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA
    
    # create client list's xml file
    # add_wangxb_2015027
    # 下面的是再生成一个xml文件,和上面一样
    if [ -e "$XML_DIR/$CLIENT_LIST_XML" ];
    then
        rm -f $XML_DIR/$CLIENT_LIST_XML
    fi
    
    if [ -e "$XMLSCRIPT/$CLIENT_LIST_QUERY_DATA" ];
    then
        CLIENT_LIST_QUERY_DATA="client_list_query_data_"$(date '+%Y%m%d%H%M%S')".tmp"
    fi
    
    $ORACLE_HOME/bin/sqlplus -s $ORAUSER_MND @$XMLSCRIPT/$CLIENT_LIST_QUERY_SQL > $XMLSCRIPT/$CLIENT_LIST_QUERY_DATA
    
    source "$XMLSCRIPT/$XML_FUNC_FILE" "$XML_DIR/$CLIENT_LIST_XML"
    put_head 'xml version="1.0" encoding="utf-8"'
    tag_start 'ROOT'
    if [ -s "$XMLSCRIPT/$CLIENT_LIST_QUERY_DATA" ];
    then
        datas=${XMLSCRIPT}/${CLIENT_LIST_QUERY_DATA}
        #for res in $datas
        while read res;
        do
            corporation_id=$(echo $res | awk 'BEGIN {FS="\^\*\^"} {print $1}')
            corporation_name=$(echo $res | awk 'BEGIN {FS="\^\*\^"} {print $2}')
            client_id=$(echo $res | awk 'BEGIN {FS="\^\*\^"} {print $3}')
            client_print_name=$(echo $res | awk 'BEGIN {FS="\^\*\^"} {print $4}')
            tag_start 'CLIENT'
            tag 0 'CORPORATION_ID' ${corporation_id:-""}
            tag 1 'CORPORATION_NAME' ${corporation_name:-""}
            tag 0 'CLIENT_ID' ${client_id:-""}
            tag 1 'CLIENT_PRINT_NAME' ${client_print_name:-""}
            tag_end 'CLIENT'
        done < $datas
    fi
    tag_end 'ROOT'
    rm $XMLSCRIPT/$CLIENT_LIST_QUERY_DATA
    
    # add_wangxb_20150304
    # Convert xml file encoding
    # 这是将xml文件进行转码,命令是iconv
    if [ -e "$XML_DIR/$MATCHING_RESULT_XML" ];
    then
        echo "********** matching_result.xmlファイルコ〖ドを啪垂し、**********"
        iconv -f euc-jp -t utf-8 $XML_DIR/$MATCHING_RESULT_XML  -o $XML_DIR/$MATCHING_RESULT_XML.utf-8
        mv $XML_DIR/$MATCHING_RESULT_XML.utf-8 $XML_DIR/$MATCHING_RESULT_XML
    fi
    if [ -e "$XML_DIR/$CLIENT_LIST_XML" ];
    then
        echo "********** client_list.xmlフィルコ〖ドを啪垂し、**********"
        iconv -f euc-jp -t utf-8 $XML_DIR/$CLIENT_LIST_XML  -o $XML_DIR/$CLIENT_LIST_XML.utf-8
        mv $XML_DIR/$CLIENT_LIST_XML.utf-8 $XML_DIR/$CLIENT_LIST_XML
    fi
    
    # add_wangxb_20150304
    # Send the xml file to the destination server by ftp
    #ftp_host="222.***.***.***"
    #USER="***"
    #PASS="***"
    #ftp -i -n $ftp_host << EOF
    #user $USER $PASS
    #cd /
    #lcd $XML_DIR/
    #put $MATCHING_RESULT_XML
    #put $CLIENT_LIST_XML
    #quit
    #EOF
    
    # test ftp
    # 通过ftp将xml文件放到客户服务器上,ftp_host:客户服务器地址,user登录名,pass密码
    ftp_host="***.***.***.***"
    USER="***"
    PASS="***"
    dir="/upload"
    ftp -i -n $ftp_host << EOF
    user $USER $PASS
    cd /upload/
    lcd $XML_DIR/
    put $MATCHING_RESULT_XML
    put $CLIENT_LIST_XML
    quit
    EOF
    
    # Save the program log file
    YYMM=$(date +'%Y%m%d%H%M')
    cp /tmp/create_xml.log /usr/p3s/batch/jaaa_match/tmp_xa_wangxb/logs/create_xml.log.$YYMM
    
    # Send error log files into the Admin mailbox
    info_to_mail_1="**@**.co.jp"
    info_to_mail_2="***@**.co.jp"
    # nkf 日文转码的一个命令
    title=$(echo "test" | nkf -j)
    nkf -j < /tmp/create_xml.log | mail -s $title $info_to_mail_1 $info_to_mail_2
    
    #exit

    关于nkf 日文转码:http://www.cnblogs.com/wxb0328/p/4333820.html

    本来是用scp传送的,但是后面修改了,这里把自己为scp传送找到的一个,不用密码可立即登入的 ssh 用户

    在鸟哥私房菜的服务器架设篇的第十一章中有介绍:http://vbird.dic.ksu.edu.tw/linux_server/0310telnetssh_2.php#ssh_nopasswd

    下面是执行的两个sql文件

    SET PAGESIZE 0
    SET FEEDBACK OFF
    SET VERIFY OFF
    SET ECHO OFF
    SET HEADING OFF
    SET TIMI OFF
    SET LINESIZE 1000
    SET WRAP OFF
    
    SELECT s.STOCKID|| '^*^' ||a.SERI_NO|| '^*^' ||a.MATCH_FLG|| '^*^' ||a.UNMATCH_RIYUU|| '^*^' ||to_char(a.UP_DATE,'YYYY-MM-DD@HH24:MI:SS') UP_DATE FROM aaa_stock_db a LEFT JOIN SENDDATAAPPRAISALPROTO s ON a.SERI_NO=s.SEIRINO WHERE a.UP_DATE BETWEEN to_date('&1','yyyy-mm-dd hh24:mi:ss') AND to_date('&2','yyyy-mm-dd hh24:mi:ss') AND a.DEL_FLG=0 ORDER BY a.UP_DATE DESC;
    
    exit
    SET PAGESIZE 0
    SET FEEDBACK OFF
    SET VERIFY OFF
    SET ECHO OFF
    SET HEADING OFF
    SET TIMI OFF
    SET LINESIZE 1000
    SET WRAP OFF
    
    SELECT a.CORPORATION_ID|| '^*^' ||a.CORPORATION_NAME|| '^*^' ||b.CLIENT_ID|| '^*^' ||(select CLIENT_PRINT_NAME from CLIENT_MASTER where CLIENT_ID = b.CLIENT_ID) as CLIENT_PRINT_NAME FROM M_CORPORATION_MASTER a LEFT JOIN M_CORPORATION_GROUP b ON (a.CORPORATION_ID = b.CORPORATION_ID) WHERE a.DEL_FLG=0 AND b.DEL_FLG=0;
    
    exit

    三、来看看效果

    当然中间出现了许多bug,不过慢慢修改吗,兵来将挡,水来土掩,bug来了自己调么

    就这样简单的整理一下,可能光这么写不够完整,但是,中间设计的知识也很多,不能展开了说,做个分享,大家有用到的时候也是个思路,具体的某些知识点可以用到了再去找资料了。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    抖音安全与信任开放日:揭秘推荐算法,告别单一标签依赖

    ultraedit编辑器打开文件时,总是提示是否转换为DOS格式,如何关闭?

    Cornell大神Kleinberg的经典教材《算法设计》是最好入门的算法教材

    从 Microsoft 下载中心安装 Windows 7 SP1 和 Windows Server 2008 R2 SP1 之前要执行的步骤

    Llama 2基于UCloud UK8S的创新应用

    火山引擎DataTester:如何使用A/B测试优化全域营销效果

    腾讯云、移动云继阿里云降价后宣布大幅度降价

    字节跳动数据平台论文被ICDE2023国际顶会收录,将通过火山引擎开放相关成果

    这个话题被围观超10000次,火山引擎VeDI如此解答

    误删库怎么办?火山引擎DataLeap“3招”守护数据安全

    IT头条

    平替CUDA!摩尔线程发布MUSA 4性能分析工具

    00:43

    三起案件揭开侵犯个人信息犯罪的黑灰产业链

    13:59

    百度三年开放2.1万实习岗,全力培育AI领域未来领袖

    00:36

    工信部:一季度,电信业务总量同比增长7.7%,业务收入累计完成4469亿元

    23:42

    Gartner:2024年全球半导体营收6559亿美元,AI助力英伟达首登榜首

    18:04

    技术热点

    iOS 8 中如何集成 Touch ID 功能

    windows7系统中鼠标滑轮键(中键)的快捷应用

    MySQL数据库的23个特别注意的安全事项

    Kruskal 最小生成树算法

    Ubuntu 14.10上安装新的字体图文教程

    Ubuntu14更新后无法进入系统卡在光标界面解怎么办?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。