当前位置:Linux教程 - Shell - shell - 把csh,sh或ksh语法的脚本相互转换的程序

shell - 把csh,sh或ksh语法的脚本相互转换的程序

把csh,sh或ksh语法的脚本相互转换的程序
2004-04-23 15:18 pm
来自:Linux文档
现载:Www.8s8s.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 ([email protected])
# Enhanced version by:Brian Hiles ([email protected])
#
# 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 "
" print } "
"# 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
print
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
print
#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的区别,乐事也