| 您的位置:首页 > 文档 > Shell > |
文章分类热门文章 |
把csh,sh或ksh语法的脚本相互转换的程序创建:2005-10-26 00:49:45 作者:Unlinux 来自: http://www.Unlinux.com 把csh,sh或ksh语法的脚本相互转换的程序 这是我找到的一个csh2ksh converter. 你可以用一下看. #!/usr/bin/nawk -f #*TAG:35739 34:Apr 17 1996:0755:sh.d/csh2ksh:csh2ksh: # csh2ksh 1.4 #************************************************************************ # Original by:Daniel Zepeda (daniel.zepeda@waii.com) # Enhanced version by:Brian Hiles (bsh20858@challenger.atc.fhda.edu) # # This script will change a C-Shell script into a Korn Shell script. # usage: csh2ksh <script.csh> # # Obviously, this script isn't going to pick up every little thing. # You can do yourself a big favor by splitting multiple commands per line. # Makes a half-hearted attempt to substitute multiple commands per line. #************************************************************************ # glob (ksh N/I), hash (csh N/I), rehash, hashstat (N/I) # get this to work on /usr/bin/vgrind, /usr/local/src/tcpdump-3.0/configure # Each occurrence of a foreach, switch, while, if...then and else built-in # must appear as the first word on its own input line. # passthru!="ON" && /.../ { # option to pass through/don't pass through unconvertable tokens # Keep track of goto labels; if encountered, turn into a # function, else make into an "exit" (special case "_bailout"). # Strip comments, place in buffer to be re-appended to $0 at EOR. # It has to be assumed that syntactic units will be EOL, semicolon delimited BEGIN { #XXX need to save IFS? (always reinitialized to ' ') # Any functs below may be elim'd if script does not use feature. # However, make sure to elim the respective alias and declaration! # prevcase=-1 if (ENVIRON["passthru"]!="") #XXX # flag to pass through unsubstitutable tokens to output print "passthru=" (passthru="ON") >"/dev/tty" if (ENVIRON["casualvars"]!="") # flag to suppress the assumption of variables being arrays print "casualvars=" (casualvars="ON") >"/dev/tty" if (ENVIRON["nopreamble"]!="") # flag to suppress the output of the env preamble code print "nopreamble=" (nopreamble="ON") >"/dev/tty" if (nopreamble!="ON") print "#!ksh " "set -A argv '' "$@" " "home=$HOME mail=$MAIL prompt=$PS1 shell=$SHELL " "term=$TERM user=$USER _IFS=$IFS IFS=: " "set -A cdpath '' $CDPATH; set -A path '' $PATH " "IFS=" $_IFS" alias chdir=cd login='exec /bin/login' " "nice='nice ' rehash='PATH=$PATH' unhash='set +o traceall' " "set -o nounset " "# ## any of the following functions+attributes and/or aliases " "## may be eliminated if that feature is not used in this script # " "# avail to serve the usual purpose of a label at or near EOF " "function _bailout " "{ exit } " "# directory stack: nec to maintain correct dirstack upon chdir " "alias _cd=cd; typeset -fx _cd " "function _cd " "{ # make top of directory stack cwd " " set -o noglob +o nounset " " cd "$@" && set +A _dirstack ~+/ } " "# emulate the csh implementation of "limit" " "alias limit=_limit; typeset -fx _limit " "function _limit " "{ eval ulimit -a ${1:+| " "egrep "^(nofiles()?${1#cpu}" || " " print -ru2 limit -- No such limit} } " "# emulate the csh implementation of "shift" " "alias shift=_shift; typeset -fx _shift " "function _shift " "{ if [[ ${1-argv} = argv ]] " " then trap 'set -- "${argv[@]}" " " shift 2 " " set -A argv "" "$@"' EXIT " " else typeset _varx=$1 " " eval set -- ""${$1[@]?}"" " " shift " " set -A $_varx "$@" " " fi } " "# emulate the csh implementation of "source" " "typeset -fx _source " "function _source " "{ if file ${1:?source -- Too few arguments} 2>&- | " " grep -s '/bin/k?sh' " " then trap '. "$@"' EXIT " " else print -u2 cannot source "$1" -- not k/sh script " " exit 1 " " fi } " "# directory stack: emulate the csh implementation of "dirs" " "typeset -fx dirs " "function dirs " "{ # display directory stack " " set -o noglob +o nounset " " typeset dir " " (($#>=2)) && " " { print -ru2 'dirs: Too many arguments' " " return 1 " " } " " if [[ $1 = -l ]] " " then for dir in ${_dirstack[*]:-$PWD/} " " do print -nr -- "${dir%/} " " " done " " else for dir in ${_dirstack[*]:-$PWD/} " " do dir=${dir#$HOME/} " " case $dir in " " ('') print -nr -- '~ ' ;; " " (/*) print -nr -- "${dir%/} " ;; " " (*) print -nr -- "~/${dir%/} " ;; " " esac " " done " " fi " } " "# directory stack: emulate the csh implementation of "popd" " "typeset -fx popd " "function popd " "{ # cd to and/or delete stack entry " " set -o noglob +o nounset " " if ((!$#)) " " then # pop directory off the stack, cd to new top " " if cd ${_dirstack[1]:?Directory stack empty.} " " then unset _dirstack[0] " " set -A _dirstack ${_dirstack[*]} " " dirs " " else unset _dirstack[0] " " set -A _dirstack ${_dirstack[*]} " " return 1 " " fi " " elif [[ $# = 1 && $1 = ++([0-9]) ]] " " then # case of popd +n: delete nth dir from stack " " typeset -i ndir " " set ${1#+} " " # uncomment to use last element if param exceeds permissible: " " #let "$1 > (ndir=${#_dirstack[*]}-1)" && set -- $ndir " " let "$1 > ${#_dirstack[*]}-1" && " " { print -u2 'popd: Directory stack not that deep.' " " return 1 " " } " " (($1<=0)) && " " { print -u2 'popd: Bad directory.' " " return 1 " " } " " unset _dirstack[$1] " " set -A _dirstack ${_dirstack[*]} " " dirs " " else print -u2 'popd: Too many arguments.' " " return 1 " " fi } " "# directory stack: emulate the csh implementation of "pushd" " "typeset -fx pushd " "function pushd " "{ # make new top of stack cwd " " set -o noglob +o nounset " " if ((!$#)) " " then # case of pushd without args; swap top two directories " " if cd ${_dirstack[1]:?No other directory.} 2>&- " " then set +A _dirstack ${_dirstack[1]} ${_dirstack[0]} " " dirs " " else print -ru2 " " "pushd: ${_dirstack[1]}: No such file or directory." " " return 1 " " fi " " elif [[ $# = 1 && $1 = ++([0-9]) ]] " " then # case of pushd +n: rotate left n times directory stack " " typeset -i ndir nrot=${1#+} " " typeset firstdir " " # uncomment to use last element if param exceeds permissible: " " #let "nrot+1>(ndir=${#_dirstack[*]})" && let nrot=ndir-1 " " let "nrot > (ndir=${#_dirstack[*]}-1)" && " " { print -ru2 'pushd: Directory stack not that deep.' " " return 1 " " } " " ((nrot<=0)) && " " { print -ru2 'pushd: +0: No such file or directory.' " " return 1 " " } " " while let '(nrot-=1)>=0' " " do firstdir=${_dirstack[0]} " " unset _dirstack[0] " " set -A _dirstack ${_dirstack[*]} $firstdir " " done " " cd ${_dirstack[0]} && dirs " " elif (($#==1)) " " then # one argument is directory to push " " if cd ${1:?No such file or directory.} 2>&- " " then set -A _dirstack ~+/ ${_dirstack[*]:-$OLDPWD/} " " dirs " " else print -ru2 "pushd: $1: No such file or directory." " " return 1 " " fi " " else print -ru2 'pushd: Too many arguments.' " " return 1 " " fi } " "LINENO=0" } {donescan="OFF" }# like a "next" command, except ... /^[ ]*($|#)/ {# empty line or comment # Suppress newlines between case patterns, so that # introduced escaped newlines will act appropriately. if (prevcase==NR-1) prevcase+=1 else next } {gsub("[ ]+;", ";")# so that "command ;" !~ /command[ ]/ if ($0!~/[ ]+/) sub("[ ]+$", "") sub(";$", "") } /$/ {# normalize and convert variable syntax #XXX must appear before `.*` gsub("${?", "${#"); gsub("$?", "$#") gsub("${?#?[A-Za-z_][A-Za-z_0-9]+([.*]])?}?", "!<!&!>!") gsub("$[1-9]", "!<!&!>!") # # delimit variable with braces, if none exist: gsub("!>![", "[") if (gsub("]", "&}")) gsub("]}}", "]}") if (gsub("!<!$", "&{")) gsub("!<!${{", "!<!${") if (gsub("!>!", "}&")) gsub("}}!>!", "}!>!") # # add default "[@]" array indices, if none exist: gsub("[*]", "[@]")# [*] -> [@] # turn positional parameters into argv array r-values (for robustness) if (casualvars!="ON") if (gsub("${[1-9]}!>!", "${argv[!#!&!#!")) {gsub("!#!${", "") gsub("}!>!!#!", "]}") } if (casualvars!="ON") if (gsub("}!>!", "[@]&")) gsub("[@][@]", "[@]")# ${var} -> ${var[@]} gsub("}[", "[")# ${var}[ -> ${var[ # # substitute special variables: gsub("$#0", "${0:+1}")# special case: $?0 must be in ((...)) gsub("${status[@]}", "$?") gsub("${child[@]}", "$!") gsub("${cwd[@]}", "${PWD}") # # miscellaneous: gsub("![<>]!", "") #XXXgsub(":g[ehrtq]", "")# specifiers won't work on array elmts gsub(":q", "")# implement instead using dquotes! gsub("}:e", "##*.}") gsub("}:h", "%/*}") gsub("}:r", "%.*}") gsub("}:t", "##*/}") } /(^|[ ;&|])set[ ]/ {# set command syntax #XXX $0 alert! (must then be EOL) # "set var = ( ... )" # -xor- # "set var = value" -or- "set var=value" -or- "set var" # "set echo/ignoreeof/noclobber/noglob/nonomatch/notify/verbose" sub("(^|[ ]+)set[ ]+", "") if (gsub("[ ]+=", "=")) gsub("=[ ]+", "=") if ($0~")($|[ ])") {# "set var=(...)" -> "set -A var ... ;" gsub("[^ ]+=(", " ; set -A &") gsub("=(", " ") gsub(")", " ; ") gsub("set -A argv[^;]*", "& && set -- "${argv[@]}"") sub("^ ; ", "") } else {#XXX quoted text may get changed!! $0=" " $0 " " gsub("[ ]+", " ") gsub(" [A-Za-z_0-9]+ ", " &= ") gsub(" +=", "=") sub("^ +", "") #XXX print "DEBUG: |" $0 "|" >"/dev/tty" # "set echo/ignoreeof/noclobber/noglob/nonomatch/notify/verbose" sub("echo=", ";set -o xtrace ;") sub("ignoreeof=", ";set -o ignoreeof ;") sub("noglob=", ";set -o noglob ;") sub("nonomatch=", ";set -o verbose ;") sub("verbose=", ";set -o verbose ;") } } /(^|[ ;&|])source[ ]/ {# source script #XXX either this or function _source defined above! if (nopreamble=="ON") gsub("source[ ]+", ". ") } /(^|[ ;&|])echo($|[ ])/ {# echo -> print gsub("echo[ ]*", "print -- ") sub("print -- -n[ ]", "print -n -- ") } /(^|[ ;&|])foreach[ ].*(.*)/ {# foreach -> for ... do # warning! (.*) must appear on the same line #XXX must appear before (.*) part #XXX $2 alert! (foreach must then be BOL) gsub("foreach", "for ") sub($2, $2 " in ") gsub("(", "") gsub(")", " ; do ") } /(^|[ ;&|])while[ ]+(.*)/ {# while -> while ... do # warning! (.*) must appear on the same line gsub("(", "") gsub(")", " ; do ") } /(^|[ ;&|])goto[ ]/ {# goto -> funct call (see docs) #XXX must appear before "case" part #XXX can goto's be right semi delimited ? # _Back_ reference(s) and/or _one_ skip-to-EOF # label ("_bailout") are the only ones permitted. gsub("goto[ ]+_?", "_") label[$1]=$1 } /(^|[ ;&|])case[ ].*/ {# case -> case-pattern # warning! must appear rightmost #XXX must appear before label part if (prevcase!=NR-1) gsub("case[ ]+", "") else gsub("case[ ]+", "|") gsub(":", "") # for multiple "case" statements having appeared on same line: #XXX gsub("[ ]+|?", " | ") prevcase=NR } /(^|[ ;&|])switch[ ]+(.*)/ {# switch -> case ... { # warning! must not appear with another (.*) #XXX (.*) must appear on the same line gsub("switch[ ]+", "case ") gsub("(", " ") gsub(")", " { ") } /(^|[ ;&|])breaksw$/ {# breaksw -> ;; # warning! you _must_ use the (optional!) "breaksw" command #XXX can this be right semi delimited? gsub("breaksw", " ;; ") } /(^|[ ;&|])endsw$/ {# endsw -> esac #XXX can this be right semi delimited ? gsub("endsw", "}") } /(^|[ ;&|])alias[ ]/ {# alias syntax #XXX $0 alert! (must then be EOL) # unalias is meant to pass through # "csh: alias var 1 2" -> "alias var (1 2)" sub("alias[ ]+[A-Za-z_0-9]+[ ]", "&!<!") #XXX sub(" !<!", "='") $0=$0 "'" } /(^|[ ;&|])setenv($|[ ])/ {# setenv -> export #XXX $2 alert! (must then be BOL) #XXX $0 alert! (must then be EOL) #XXX can this be right semi delimited ? gsub("setenv", "export ") if ($2!="") {sub($2, $2 "=") sub("=[ ]*", "='") $0=$0 "'" } } /(^|[ ;&|])end$/ {# end -> done #XXX can this be right semi delimited ? gsub("end", "done") } /(^|[ ;&|])endif$/ {# endif -> fi # csh: must be the first word on the line #XXX can this be right semi delimited ? gsub("endif", "fi") } /(^|[ ;&|])(else[ ]+)?if[ ]*(/ {# else if -> elif # csh: must be the first word on the line #XXX must appear before "if" part gsub("else[ ]+if[ ]*", "elif ") } /(^|[ ;&|])(el)?if[ ]*(.*)/ {# (else)if/then syntax # warning! (.*) must appear on the same line #XXX except when their is no "then" part! #XXX $0 alert! (must then be EOL) ?? if ($0~/)[ ]+then($|[ ])/) {gsub(")[ ]+then($|[ ])", ") ; then ") } else {# if ... syntax -> ... && gsub("if[ ]+(", "( ") gsub(")[ ]+", ") && ") } } /(.*)/ {# expression syntax # warning! (.*) part must appear on the same line #XXX need to convert to ((...)) when applicable #gsub("&&", " ]] && [[ ") #gsub("||", " ]] || [[ ") # # (...)grouping # ~one's complement # !logicalnegation # * / %multiplication,division, remainder (These are # right associative, which can lead to # unexpected results. Group combinations # explicitly withparentheses.) # + -addition, subtraction (also right associative) # << >>bitwiseshift left, bitwise shift right # < > <= >=less than, greater than, less than or equal # to, greater than or equal to # == != =~ !~equal to, not equal to,filename-substitution # patternmatch (described below), filename- # substitution pattern mismatch # &bitwiseAND # ^bitwiseXOR (exclusive or) # |bitwiseinclusive OR # &&logicalAND # ||logicalOR # #XXX change into ((...)) or [[ ... ]], where appropriate. gsub("(", " [[ ") gsub(")", " ]] ") gsub("==", "=") gsub("=~", "=") gsub("!~", "!=") gsub("<=", "-le") gsub(">=", "-ge") gsub(">", "-lt") gsub("<", "-gt") } /[ ="']`.*`/ {# command substitution syntax #XXX must be after expression part #XXX do csh bquotes need to both be on the same line? while (sub("`", "$(")) sub("`", ")") } /$</ {# $< -> read ... #XXX must appear after expression syntax #XXX set var = ($<) ?? gsub("$<", "$(line)") #gsub("=$<", "") #gsub($1, "read " $1) } /(^|[ ;&|])unalias[ ]/ {# unalias syntax #XXX unalias with no arguments is meant to pass through #XXX will choke on escaped file substitution words! gsub("*", ".*", $2) gsub("?", ".", $2) gsub("unalias[ ]+", "unalias $(typeset +|grep '^" $2 "$')") } /(^|[ ;&|])unset[ ]/ {# unset syntax #XXX must appear after `.*` and expression parts #XXX will choke on escaped file substitution words! gsub("*", ".*", $2) gsub("?", ".", $2) gsub("unset[ ]", "unset $(typeset +|grep '^" $2 "$')") } #XXX /XXX(^|[ ;&|)@($|[ ])/ {# @ -> let #XXX must appear after expresssion part #XXX does "@" have a significance to a "nawk" r.e. ?? if ($2!="") {sub("@[ ]+", "(( ") $0=$0 " ))" } else {sub("@", "typeset -") } } /(^|[ ;&|])onintr($|[ ])/ {# interrupt trapping #XXX $0 alert (must then be EOL!) if ($0~/onintr$/) {$0="trap -" } else if ($0~/[ ]-$/) {$0="trap ''" } else {gsub("onintr[ ]+", "trap _") $0=$0 " INT" } } /^[ ]*default:$/ {# default: -> *) #XXX must appear before "label" part gsub("default:", "*)") } /(^|[ ;&|])[A-Za-z_][A-Za-z_0-9]*:$/ {# goto label -> function definition #XXX $0 alert! (must then be EOL) # The special label "_bailout" should be used # for the usual purpose of breaking to EOF. if ($0~/(^|[ ]+)_?bailout:$/) next# already defined as function above sub("[A-Za-z_0-9]+:", "_&") sub(":", " () { eval ${1:+trap "set -- $@; set -A argv "$@"" EXIT}") } />&?(?!)?/ {# redirection operators syntax # > >! >& >&! # >> >>& >>! >>&! gsub(">>&", " 2!#!&1 !#!>") gsub(">&", " 2>&1 >") gsub("!#!", ">") gsub(">()?!", ">|") gsub(">>|", ">>")# because ">>|" is ksh syntax error } {gsub(" +", " ")# strip redundant spaces #XXX this should be subsumed by escnl rejoined in prior pass if ($0~/[&|][ ]+$/) # "|", "||", "&&" operators don't need escaped newline $0=substr($0, 1, length($0)-2) sub(" ", " ") sub("[ ]+$", "")# strip any trailing whitespace sub("[^;];$", "")# strip any trailing semicolon sub("[^;];$", "")# and do it again (#XXXtry "@" feature) if (!prevcase || prevcase==NR-1) # append right paren delimiting multi-line case patterns $0=") " $0 #printf "%2d,%2d: %s ", NR, prevcase, $0 } END { #XXX undefined hash print order! # for every "onintr" label turned into a function... for (key in label) if (key!="_bailout") print "}; " label[key] } 偶觉得不太会有这种自动转换程序吧,其实自己手工转换一下,正好熟悉几种shell的区别,乐事也 转载自:http://www.unlinux.com/doc/shell/20051026/240.html 【评论】 【加入收藏夹】 【大 中 小】 【打印】 【关闭】 ※ 相关链接 无相关信息 |