搜索
首页后端开发XML/RSS教程用Shell脚本生成XML文件实例详解

用Shell脚本生成XML文件实例详解

Apr 21, 2017 pm 05:14 PM
外壳脚本xml

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

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

具体是这样:

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

具体实现步骤:

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

#! /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 &#39;<&#39;${*}&#39;>&#39; >> $outfile
}

# 这里也是输出一个xml的节点,只是比上面的节点有更多的设置
# ${@:2} 的意思:它的值就是由第二个参数开始到最后一个参数,为什么要这样?有时可能你的第二个参数中有空格,shell接受参数是以空格计算的
put_tag() {
    echo &#39;<&#39;$1&#39;>&#39;${@:2}&#39;</&#39;$1&#39;>&#39; >> $outfile
}
# 同样是一个输出节点函数,但是添加了CDATA,防止特殊字符造成xml解析失败
put_tag_cdata() {
    echo &#39;<&#39;$1&#39;><![CDATA[&#39;${@:2}&#39;]]></&#39;$1&#39;>&#39; >> $outfile
}

put_head(){
    put &#39;?&#39;${1}&#39;?&#39;
}
# 这是一个缩进的算法,自行理解
out_tabs(){
    tmp=0
    tabsstr=""
    while [ $tmp -lt $((tabs)) ]
    do
        tabsstr=${tabsstr}&#39;\t&#39;
        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 &#39;/&#39;${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中我们可以也可以使用${}包含变量名,来调用变量

二、从数据库查数据利用上面的函数,制作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 &#39;+%Y%m%d_%H%M%S&#39;)".xml"
MATCHING_RESULT_QUERY_DATA="matching_result_query_data.tmp"
MATCHING_RESULT_QUERY_SQL="matching_result_query.sql"

CLIENT_LIST_XML="client_list_"$(date &#39;+%Y%m%d_%H%M%S&#39;)".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 &#39;+%Y%m%d%H%M%S&#39;)".tmp"
fi
#+++++++++++++++++++++++++++++++++++++++++++++++++
# add_wangxb_20150225
# check system time,  choice query time period
# 这是是根据crontab每天执行的时间,取得我们查询数据库时的where条件的时间区间
#+++++++++++++++++++++++++++++++++++++++++++++++++
sys_datetime=$(date &#39;+%Y%m%d%H&#39;)
first_chk_datetime="$(date &#39;+%Y%m%d&#39;)04"
second_chk_datetime="$(date &#39;+%Y%m%d&#39;)12"
third_chk_datetime="$(date &#39;+%Y%m%d&#39;)20"
# 由于服务器crontab是上面的时间,但是执行的shell比较多,在调用我这个shell的时候,不一定就是04:30 ,12:30, 20:30所以,这里的根据系统的时间判断时 范围给的比较宽
case $sys_datetime in
    "$first_chk_datetime"|"$(date &#39;+%Y%m%d&#39;)05"|"$(date &#39;+%Y%m%d&#39;)06"|"$(date &#39;+%Y%m%d&#39;)07")
        chk_start=$(date &#39;+%Y-%m-%d 21:00:00&#39; -d &#39;-1 day&#39;)
        chk_end=$(date &#39;+%Y-%m-%d 04:29:59&#39;)
    ;;
    "$second_chk_datetime"|"$(date &#39;+%Y%m%d&#39;)13"|"$(date &#39;+%Y%m%d&#39;)14"|"$(date &#39;+%Y%m%d&#39;)15")
        chk_start=$(date &#39;+%Y-%m-%d 04:30:00&#39;)
        chk_end=$(date &#39;+%Y-%m-%d 12:29:59&#39;)

    ;;
    "$third_chk_datetime"|"$(date &#39;+%Y%m%d&#39;)21"|"$(date &#39;+%Y%m%d&#39;)22"|"$(date &#39;+%Y%m%d&#39;)23")
        chk_start=$(date &#39;+%Y-%m-%d 12:30:00&#39;)
        chk_end=$(date &#39;+%Y-%m-%d 20:59:59&#39;)

    ;;
    *)
        chk_start=$(date &#39;+%Y-%m-%d 00:00:00&#39;)
        chk_end=$(date &#39;+%Y-%m-%d 23:59:59&#39;)

    ;;
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=&#39;YYYY-MM-DD:HH24:MI:SS&#39;;
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&#39;s xml file
# add_wangxb_20150227
# 下面的算法就是将查出的数据进行分析,调用xml函数生成xml文件
source "$XMLSCRIPT/$XML_FUNC_FILE" "$XML_DIR/$MATCHING_RESULT_XML"
put_head &#39;xml version="1.0" encoding="utf-8"&#39;
tag_start &#39;ROOT&#39;
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 &#39;BEGIN {FS="\\^\\*\\^"} {print $1}&#39;)
        seirino=$(echo $res | awk &#39;BEGIN {FS="\\^\\*\\^"} {print $2}&#39;)
        match_flg=$(echo $res | awk &#39;BEGIN {FS="\\^\\*\\^"} {print $3}&#39;)
        unmatch_riyuu=$(echo $res | awk &#39;BEGIN {FS="\\^\\*\\^"} {print $4}&#39;)
        up_date_tmp=$(echo $res | awk &#39;BEGIN {FS="\\^\\*\\^"} {print $5}&#39;)
        up_date=$(echo $up_date_tmp | awk &#39;BEGIN {FS="@"} {print $1 " " $2}&#39;)
        tag_start &#39;MATCHING&#39;
        tag 0 &#39;STOCKID&#39; ${stock_id:-""}
        tag 0 &#39;SEIRINO&#39; ${seirino:-""}
        tag 0 &#39;RESULT&#39; ${match_flg:-""}
        tag 1 &#39;REASON&#39; ${unmatch_riyuu:-""}
        tag 0 &#39;UPDATE_DATE&#39; ${up_date:-""}
        tag_end &#39;MATCHING&#39;
    done < $datas
fi
tag_end &#39;ROOT&#39;
rm $XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA

# create client list&#39;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 &#39;+%Y%m%d%H%M%S&#39;)".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 &#39;xml version="1.0" encoding="utf-8"&#39;
tag_start &#39;ROOT&#39;
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 &#39;BEGIN {FS="\\^\\*\\^"} {print $1}&#39;)
        corporation_name=$(echo $res | awk &#39;BEGIN {FS="\\^\\*\\^"} {print $2}&#39;)
        client_id=$(echo $res | awk &#39;BEGIN {FS="\\^\\*\\^"} {print $3}&#39;)
        client_print_name=$(echo $res | awk &#39;BEGIN {FS="\\^\\*\\^"} {print $4}&#39;)
        tag_start &#39;CLIENT&#39;
        tag 0 &#39;CORPORATION_ID&#39; ${corporation_id:-""}
        tag 1 &#39;CORPORATION_NAME&#39; ${corporation_name:-""}
        tag 0 &#39;CLIENT_ID&#39; ${client_id:-""}
        tag 1 &#39;CLIENT_PRINT_NAME&#39; ${client_print_name:-""}
        tag_end &#39;CLIENT&#39;
    done < $datas
fi
tag_end &#39;ROOT&#39;
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 +&#39;%Y%m%d%H%M&#39;)
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

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

下面是执行的两个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|| &#39;^*^&#39; ||a.SERI_NO|| &#39;^*^&#39; ||a.MATCH_FLG|| &#39;^*^&#39; ||a.UNMATCH_RIYUU|| &#39;^*^&#39; ||to_char(a.UP_DATE,[email protected]:MI:SS&#39;) UP_DATE FROM aaa_stock_db a LEFT JOIN SENDDATAAPPRAISALPROTO s ON a.SERI_NO=s.SEIRINO WHERE a.UP_DATE BETWEEN to_date(&#39;&1&#39;,&#39;yyyy-mm-dd hh24:mi:ss&#39;) AND to_date(&#39;&2&#39;,&#39;yyyy-mm-dd hh24:mi:ss&#39;) 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|| &#39;^*^&#39; ||a.CORPORATION_NAME|| &#39;^*^&#39; ||b.CLIENT_ID|| &#39;^*^&#39; ||(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来了自己调么

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

以上是用Shell脚本生成XML文件实例详解的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
掌握良好的XML:数据交换的最佳实践掌握良好的XML:数据交换的最佳实践May 14, 2025 am 12:05 AM

良好形式的XMliscrucialfordAtaExchangeBecapeparsingSiturscrectparsingandSundStandingAcrossystem.1)startwithAdeClarationLike.2)确保everyveryopentingtaghasaclopingtaghasaclosingtagosingtagandelementsareproproproproproperlynested.3)

XML:它仍然使用吗?XML:它仍然使用吗?May 13, 2025 pm 03:13 PM

Xmlisstillusedduetoitsstructusednature,人类可读性,以及范围的addionindererpriseEnvormentments.1)itfacilitatesdataexchangeInsectInsectorlikeFinance(swift)andHealthCare(hl7)和hl7)

RSS文档的解剖结构:结构和元素RSS文档的解剖结构:结构和元素May 10, 2025 am 12:23 AM

RSS文档的结构包括三个主要元素:1.:根元素,定义RSS版本;2.:包含频道信息,如标题、链接、描述;3.:代表具体的内容条目,包含标题、链接、描述等。

了解RSS文档:综合指南了解RSS文档:综合指南May 09, 2025 am 12:15 AM

RSS文档是一种简便的订阅机制,通过XML文件发布内容更新。1.RSS文档结构由和元素组成,包含多个。2.使用RSS阅读器订阅频道,并通过解析XML提取信息。3.高级用法包括使用feedparser库进行过滤和排序。4.常见错误包括XML解析和编码问题,调试时需验证XML格式和编码。5.性能优化建议包括缓存RSS文档和异步解析。

RSS,XML和现代网络:内容联合深度潜水RSS,XML和现代网络:内容联合深度潜水May 08, 2025 am 12:14 AM

RSS和XML在现代Web中依然重要。1.RSS用于发布和分发内容,用户可通过RSS阅读器订阅并获取更新。2.XML作为标记语言,支持数据存储和交换,RSS文件基于XML。

基础知识超越:XML启用的高级RSS功能基础知识超越:XML启用的高级RSS功能May 07, 2025 am 12:12 AM

RSS可以实现多媒体内容嵌入、条件订阅、以及性能和安全性优化。1)通过标签嵌入多媒体内容,如音频和视频。2)使用XML命名空间实现条件订阅,允许订阅者根据特定条件筛选内容。3)通过CDATA节和XMLSchema优化RSSFeed的性能和安全性,确保稳定性和符合标准。

解码RSS:Web开发人员的XML底漆解码RSS:Web开发人员的XML底漆May 06, 2025 am 12:05 AM

RSS是一种基于XML的格式,用于发布常更新的数据。作为Web开发者,理解RSS能提升内容聚合和自动化更新能力。通过学习RSS结构、解析和生成方法,你将能自信地处理RSSfeeds,优化Web开发技能。

JSON与XML:为什么RSS选择XMLJSON与XML:为什么RSS选择XMLMay 05, 2025 am 12:01 AM

RSS选择XML而不是JSON是因为:1)XML的结构化和验证能力优于JSON,适合RSS复杂数据结构的需求;2)XML当时有广泛的工具支持;3)RSS早期版本基于XML,已成标准。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具