- 论坛徽章:
- 0
|
把csh,sh或ksh语法的脚本相互转换的程序
这是我找到的一个csh2ksh converter.
你可以用一下看.
#!/usr/bin/nawk -f
#*TAG:35739 34:Apr 17 1996:0755:sh.d/csh2ksh:csh2ksh:
# csh2ksh 1.4
#************************************************************************
# Original byaniel 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 ' \t\n')
# 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\n" \
"set -A argv '' \"$@\"\n" \
"home=$HOME mail=$MAIL prompt=$PS1 shell=$SHELL \\\n" \
"term=$TERM user=$USER _IFS=$IFS IFS=:\n" \
"set -A cdpath '' $CDPATH; set -A path '' $PATH\n" \
"IFS=\" $_IFS\" alias chdir=cd login='exec /bin/login' \\\n" \
"nice='nice ' rehash='PATH=$PATH' unhash='set +o traceall'\n" \
"set -o nounset\n" \
"#\n## any of the following functions+attributes and/or aliases\n" \
"## may be eliminated if that feature is not used in this script\n#\n" \
"# avail to serve the usual purpose of a label at or near EOF\n" \
"function _bailout\n" \
"{\texit\n}\n" \
"# directory stack: nec to maintain correct dirstack upon chdir\n" \
"alias _cd=cd; typeset -fx _cd\n" \
"function _cd\n" \
"{\t# make top of directory stack cwd\n" \
"\tset -o noglob +o nounset\n" \
"\t\\cd \"$@\" && set +A _dirstack ~+/\n}\n" \
"# emulate the csh implementation of \"limit\"\n" \
"alias limit=_limit; typeset -fx _limit\n" \
"function _limit\n" \
"{\teval ulimit -a ${1:+\| " \
"egrep \\\"^(nofiles\\\\\\()?${1#cpu}\\\" ||\n" \
"\tprint -ru2 limit -- No such limit}\n}\n" \
"# emulate the csh implementation of \"shift\"\n" \
"alias shift=_shift; typeset -fx _shift\n" \
"function _shift\n" \
"{\tif [[ ${1-argv} = argv ]]\n" \
"\tthen\ttrap 'set -- \"${argv[@]}\"\n" \
"\t\t\\shift 2\n" \
"\t\tset -A argv \"\" \"$@\"' EXIT\n" \
"\telse\ttypeset _varx=$1\n" \
"\t\teval set -- \"\\\"\\${$1[@]?}\\\"\"\n" \
"\t\t\\shift\n" \
"\t\tset -A $_varx \"$@\"\n" \
"\tfi\n}\n" \
"# emulate the csh implementation of \"source\"\n" \
"typeset -fx _source\n" \
"function _source\n" \
"{\tif\tfile ${1source -- Too few arguments} 2>&- |\n" \
"\t\tgrep -s '/bin/k?sh'\n" \
"\tthen\ttrap '. \"$@\"' EXIT\n" \
"\telse\tprint -u2 cannot source \\\"$1\\\" -- not k/sh script\n" \
"\t\texit 1\n" \
"\tfi\n}\n" \
"# directory stack: emulate the csh implementation of \"dirs\"\n" \
"typeset -fx dirs\n" \
"function dirs\n" \
"{\t# display directory stack\n" \
"\tset -o noglob +o nounset\n" \
"\ttypeset dir\n" \
"\t(($#>=2)) &&\n" \
"\t{\tprint -ru2 'dirs: Too many arguments'\n" \
"\t\treturn 1\n" \
"\t}\n" \
"\tif [[ $1 = -l ]]\n" \
"\tthen\tfor dir in ${_dirstack:-$PWD/}\n" \
"\t\tdo\tprint -nr -- \"${dir%/} \"\n" \
"\t\tdone\n" \
"\telse\tfor dir in ${_dirstack:-$PWD/}\n" \
"\t\tdo\tdir=${dir#$HOME/}\n" \
"\t\t\tcase $dir in\n" \
"\t\t\t('')\tprint -nr -- '~ ' ;;\n" \
"\t\t\t(/*)\tprint -nr -- \"${dir%/} \" ;;\n" \
"\t\t\t(*)\tprint -nr -- \"~/${dir%/} \" ;;\n" \
"\t\t\tesac\n" \
"\t\tdone\n" \
"\tfi\n" \
"\tprint\n}\n" \
"# directory stack: emulate the csh implementation of \"popd\"\n" \
"typeset -fx popd\n" \
"function popd\n" \
"{\t# cd to and/or delete stack entry\n" \
"\tset -o noglob +o nounset\n" \
"\tif ((!$#))\n" \
"\tthen\t# pop directory off the stack, cd to new top\n" \
"\t\tif \\cd ${_dirstack[1]Directory stack empty.}\n" \
"\t\tthen\tunset _dirstack[0]\n" \
"\t\t\tset -A _dirstack ${_dirstack}\n" \
"\t\t\tdirs\n" \
"\t\telse\tunset _dirstack[0]\n" \
"\t\t\tset -A _dirstack ${_dirstack}\n" \
"\t\t\treturn 1\n" \
"\t\tfi\n" \
"\telif [[ $# = 1 && $1 = ++([0-9]) ]]\n" \
"\tthen\t# case of popd +n: delete nth dir from stack\n" \
"\t\ttypeset -i ndir\n" \
"\t\tset ${1#+}\n" \
"\t\t# uncomment to use last element if param exceeds permissible:\n" \
"\t\t#let \"$1 > (ndir=${#_dirstack}-1)\" && set -- $ndir\n" \
"\t\tlet \"$1 > ${#_dirstack}-1\" &&\n" \
"\t\t{\tprint -u2 'popd: Directory stack not that deep.'\n" \
"\t\t\treturn 1\n" \
"\t\t}\n" \
"\t\t(($1<=0)) &&\n" \
"\t\t{\tprint -u2 'popd: Bad directory.'\n" \
"\t\t\treturn 1\n" \
"\t\t}\n" \
"\t\tunset _dirstack[$1]\n" \
"\t\tset -A _dirstack ${_dirstack}\n" \
"\t\tdirs\n" \
"\telse\tprint -u2 'popd: Too many arguments.'\n" \
"\t\treturn 1\n" \
"\tfi\n}\n" \
"# directory stack: emulate the csh implementation of \"pushd\"\n" \
"typeset -fx pushd\n" \
"function pushd\n" \
"{\t# make new top of stack cwd\n" \
"\tset -o noglob +o nounset\n" \
"\tif ((!$#))\n" \
"\tthen\t# case of pushd without args; swap top two directories\n" \
"\t\tif \\cd ${_dirstack[1]No other directory.} 2>&-\n" \
"\t\tthen\tset +A _dirstack ${_dirstack[1]} ${_dirstack[0]}\n" \
"\t\t\tdirs\n" \
"\t\telse\tprint -ru2 \\\n" \
"\t\t\t\"pushd: ${_dirstack[1]}: No such file or directory.\"\n" \
"\t\t\treturn 1\n" \
"\t\tfi\n" \
"\telif [[ $# = 1 && $1 = ++([0-9]) ]]\n" \
"\tthen\t# case of pushd +n: rotate left n times directory stack\n" \
"\t\ttypeset -i ndir nrot=${1#+}\n" \
"\t\ttypeset firstdir\n" \
"\t\t# uncomment to use last element if param exceeds permissible:\n" \
"\t\t#let \"nrot+1>(ndir=${#_dirstack})\" && let nrot=ndir-1\n" \
"\t\tlet \"nrot > (ndir=${#_dirstack}-1)\" &&\n" \
"\t\t{\tprint -ru2 'pushd: Directory stack not that deep.'\n" \
"\t\t\treturn 1\n" \
"\t\t}\n" \
"\t\t((nrot<=0)) &&\n" \
"\t\t{\tprint -ru2 'pushd: +0: No such file or directory.'\n" \
"\t\t\treturn 1\n" \
"\t\t}\n" \
"\t\twhile let '(nrot-=1)>=0'\n" \
"\t\tdo\tfirstdir=${_dirstack[0]}\n" \
"\t\t\tunset _dirstack[0]\n" \
"\t\t\tset -A _dirstack ${_dirstack} $firstdir\n" \
"\t\tdone\n" \
"\t\t\\cd ${_dirstack[0]} && dirs\n" \
"\telif (($#==1))\n" \
"\tthen\t# one argument is directory to push\n" \
"\t\tif \\cd ${1No such file or directory.} 2>&-\n" \
"\t\tthen\tset -A _dirstack ~+/ ${_dirstack:-$OLDPWD/}\n" \
"\t\t\tdirs\n" \
"\t\telse\tprint -ru2 \"pushd: $1: No such file or directory.\"\n" \
"\t\t\treturn 1\n" \
"\t\tfi\n" \
"\telse\tprint -ru2 'pushd: Too many arguments.'\n" \
"\t\treturn 1\n" \
"\tfi\n}\n\n" \
"LINENO=0"
}
{donescan="OFF" }# like a "next" command, except ...
/^[\t ]*($|#)/ {# 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("[\t ]+;", ";"# so that "command ;" !~ /command[\t ]/
if ($0!~/\\[\t ]+/)
sub("[\t ]+$", ""
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", "##*/}")
}
/(^|[\t ;&|])set[\t ]/ {# 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("(^|[\t ]+)set[\t ]+", "")
if (gsub("[\t ]+=", "="))
gsub("=[\t ]+", "=")
if ($0~"\\)($|[\t ])")
{# "set var=(...)" -> "set -A var ... ;"
gsub("[^\t ]+=\\(", " ; set -A &")
gsub("=\\(", " ")
gsub("\\)", " ; ")
gsub("set -A argv[^;]*", "& \\&\\& set -- \"${argv[@]}\"")
sub("^ ; ", "")
}
else
{#XXX quoted text may get changed!!
$0=" " $0 " "
gsub("[\t ]+", " ")
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 ;")
}
}
/(^|[\t ;&|])source[\t ]/ {# source script
#XXX either this or function _source defined above!
if (nopreamble=="ON")
gsub("source[\t ]+", ". ")
}
/(^|[\t ;&|])echo($|[\t ])/ {# echo -> print
gsub("echo[\t ]*", "print -- ")
sub("print -- -n[\t ]", "print -n -- ")
}
/(^|[\t ;&|])foreach[\t ].*\(.*\)/ {# 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 ")
}
/(^|[\t ;&|])while[\t ]+\(.*\)/ {# while -> while ... do
# warning! (.*) must appear on the same line
gsub("\\(", "")
gsub("\\)", " ; do ")
}
/(^|[\t ;&|])goto[\t ]/ {# 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[\t ]+_?", "_")
label[$1]=$1
}
/(^|[\t ;&|])case[\t ].*/ {# case -> case-pattern
# warning! must appear rightmost
#XXX must appear before label part
if (prevcase!=NR-1)
gsub("case[\t ]+", "")
else
gsub("case[\t ]+", "|")
gsub(":", "\\")
# for multiple "case" statements having appeared on same line: #XXX
gsub("\\\\[\t ]+\\|?", " | ")
prevcase=NR
}
/(^|[\t ;&|])switch[\t ]+\(.*\)/ {# switch -> case ... {
# warning! must not appear with another (.*)
#XXX (.*) must appear on the same line
gsub("switch[\t ]+", "case ")
gsub("\\(", " ")
gsub("\\)", " { ")
}
/(^|[\t ;&|])breaksw$/ {# breaksw -> ;;
# warning! you _must_ use the (optional!) "breaksw" command
#XXX can this be right semi delimited?
gsub("breaksw", " ;; ")
}
/(^|[\t ;&|])endsw$/ {# endsw -> esac
#XXX can this be right semi delimited ?
gsub("endsw", "}")
}
/(^|[\t ;&|])alias[\t ]/ {# 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[\t ]+[A-Za-z_0-9]+[\t ]", "&!<!") #XXX
sub(" !<!", "='")
$0=$0 "'"
}
/(^|[\t ;&|])setenv($|[\t ])/ {# 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("=[\t ]*", "='")
$0=$0 "'"
}
}
/(^|[\t ;&|])end$/ {# end -> done
#XXX can this be right semi delimited ?
gsub("end", "done")
}
/(^|[\t ;&|])endif$/ {# endif -> fi
# csh: must be the first word on the line
#XXX can this be right semi delimited ?
gsub("endif", "fi")
}
/(^|[\t ;&|])(else[\t ]+)?if[\t ]*\(/ {# else if -> elif
# csh: must be the first word on the line
#XXX must appear before "if" part
gsub("else[\t ]+if[\t ]*", "elif ")
}
/(^|[\t ;&|])(el)?if[\t ]*\(.*\)/ {# (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~/\)[\t ]+then($|[\t ])/)
{gsub("\\)[\t ]+then($|[\t ])", ") ; then ")
}
else
{# if ... syntax -> ... &&
gsub("if[\t ]+\\(", "( ")
gsub("\\)[\t ]+", ") \\&\\& ")
}
}
/\(.*\)/ {# expression syntax
# warning! (.*) part must appear on the same line
#XXX need to convert to ((...)) when applicable
#gsub("\\&\\&", " ]] \\&\\&\n[[ ")
#gsub("\\|\\|", " ]] ||\n[[ ")
#
# (...)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")
}
/[\t ="']`.*`/ {# 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)
}
/(^|[\t ;&|])unalias[\t ]/ {# 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[\t ]+", "unalias $(typeset +|grep '^" $2 "$')")
}
/(^|[\t ;&|])unset[\t ]/ {# unset syntax
#XXX must appear after `.*` and expression parts
#XXX will choke on escaped file substitution words!
gsub("\\*", ".*", $2)
gsub("\\?", ".", $2)
gsub("unset[\t ]", "unset $(typeset +|grep '^" $2 "$')")
}
#XXX
/XXX(^|[\t ;&|)\@($|[\t ])/ {# @ -> let
#XXX must appear after expresssion part
#XXX does "@" have a significance to a "nawk" r.e. ??
if ($2!="")
{sub("@[\t ]+", "(( ")
$0=$0 " ))"
}
else
{sub("@", "typeset -")
}
}
/(^|[\t ;&|])onintr($|[\t ])/ {# interrupt trapping
#XXX $0 alert (must then be EOL!)
if ($0~/onintr$/)
{$0="trap -"
}
else if ($0~/[\t ]-$/)
{$0="trap ''"
}
else
{gsub("onintr[\t ]+", "trap _")
$0=$0 " INT"
}
}
/^[\t ]*default/ {# default: -> *)
#XXX must appear before "label" part
gsub("default:", "*)")
}
/(^|[\t ;&|])[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~/(^|[\t ]+)_?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~/[&\|][\t ]+\\$/)
# "|", "||", "&&" operators don't need escaped newline
$0=substr($0, 1, length($0)-2)
sub("\t ", "\t")
sub("[\t ]+$", "")# 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=")\n" $0
print
#printf "%2d,%2d: %s\n", 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]
}
|
|