I decided I would implement something like that but I used "print" instead
of "cat". You now delimit your blocks with:
print <<!
your text
!
You can replace "!" with any symbol you like and if you put a "-"
immediately after the "<<" then it will strip all leading tabs, like shell
here-documents.
I added a tweak that's not available in shell here-documents though - if you
specify "+" instead of "-" then the tool will only strip the number of
leading tabs that are common across all of your lines in that block. That's
so you can indent the block to look good within your script AND indent some
lines of the pre-formatted text so it looks good for output. Here's the
difference between the 3 specifications:
##################
$ cat script1.awk
BEGIN {
print << HERE
main(int argc)
{
if (argc) {
doStuff();
}
return;
}
HERE
}
$ epawk -f script1.awk
main(int argc)
{
if (argc) {
doStuff();
}
return;
}
##################
$ cat script2.awk
BEGIN {
print <<- HERE
main(int argc)
{
if (argc) {
doStuff();
}
return;
}
HERE
}
$ epawk -f script2.awk
main(int argc)
{
if (argc) {
doStuff();
}
return;
}
##################
$ cat script3.awk
BEGIN {
print <<+ HERE
main(int argc)
{
if (argc) {
doStuff();
}
return;
}
HERE
}
$ epawk -f script3.awk
main(int argc)
{
if (argc) {
doStuff();
}
return;
}
##################
The only difference in the input files above is the char that follows "<<".
All leading white space is tabs.
The resulting script is below if anyone cares, but it's gotten kinda lengthy!
Ed.
##########################################################
# Extended Print AWK
#
# Allows printing of pre-formatted blocks of multi-line text in awk scripts.
#
# Before invoking the tool, do the following IN ORDER:
#
# 1) Start each block of pre-formatted text in your script with
# print << TERMINATOR
# on it's own line and end it with
# TERMINATOR
# on it's own line. TERMINATOR can be any sequence of characters you like.
# Spaces are allowed before and/or after "print" and TERMINATOR but are
# not required. If << is followed by -, e.g.:
# print <<- TERMINATOR
# then all leading tabs are removed from the block of pre-formatted
# text (just like shell here documents), if it's followed by + instead, e.g.:
# print <<+ TERMINATOR
# then however many leading tabs are common across all non-blank lines
# in the current pre-formatted block are removed.
# By default no leading tabs are removed.
#
# 2) Within each block of pre-formatted text only:
# a) Put a backslash character (\) before every backslash.
# b) Put a backslash character before every double quote (").
# c) Enclose awk variables and and field references ($1, $2, etc.)
# in double quotes (without leading backslashes).
#
# 3) If the script is specified on the command line instead of via
# "-f script" then replace all single quote characters (') in or out
# of the pre-formatted blocks with their ANSI octal escape sequence (\047)
# or the sequence '\'' (tick backslash tick tick). This is normal and is
# required because command-line awk scripts cannot contain single quote
# characters as those delimit the script. Do not use hex \x27, see
#
http://awk.freeshell.org/PrintASingleQuote.
#
# Then just use it like you would gawk with the small caveat that only
# "-W <option>", not "--<option>", is supported for long options so you
# can use "-W re-interval" but not "--re-interval" for example.
#
# To just see the post-processed script and not execute it, call this
# script with the "-X" option.
#
##########################################################
toolName="$(basename "$0")"
expand_prints() {
gawk '
!inBlock && sub(/^[[:blank:]]*print[[:blank:]]*<</,"") {
if ( sub(/^[-]/,"") ) { skipType = "-" }
else if ( sub(/^[+]/,"") ) { skipType = "+" }
else { skipType = "" }
terminator = $0
gsub(/(^[[:blank:]]+|[[:blank:]]+$)/,"",terminator)
startBlock()
next
}
inBlock {
stripped=$0
gsub(/(^[[:blank:]]+|[[:blank:]]+$)/,"",stripped)
if ( stripped"" == terminator"" ) {
endBlock()
}
else {
updBlock()
}
next
}
{ print }
function startBlock() { inBlock=1; numLines=0 }
function updBlock() { block[++numLines] = $0 }
function endBlock( i,numSkip,indent) {
if (skipType == "") {
# do not skip any leading tabs
indent = ""
}
else if (skipType == "+") {
# skip however many leading tabs are common across
# all non-blank lines in the current pre-formatted block
for (i=1;i<=numLines;i++) {
if (block[i] ~ /[^[:blank:]]/) {
match(block[i],/^[\t]+/)
if ( (numSkip == "") || (numSkip > RLENGTH) ) {
numSkip = RLENGTH
}
}
}
for (i=1;i<=numSkip;i++) {
indent = indent "\t"
}
}
for (i=1;i<=numLines;i++) {
sub(indent,"",block[i])
print "print \"" block[i] "\""
}
inBlock=0
}
' "$@"
}
unset awkArgs
unset scriptFiles
expandOnly=0
while getopts "v:F:W:f:X" arg
do
case $arg in
f ) scriptFiles+=( "$OPTARG" ) ;;
[vFW] ) awkArgs+=( "-$arg" "$OPTARG" ) ;;
X ) expandOnly=1 ;;
* ) exit 1 ;;
esac
done
shift $(( OPTIND - 1 ))
if [ -z "${scriptFiles[*]}" -a "$#" -gt "0" ]
then
# The script cannot contain literal 's because in cases like this:
# 'BEGIN{ ...abc'def... }'
# the args parsed here (and later again by gawk) would be:
# $1 = BEGIN{ ...abc
# $2 = def... }
# Replace 's with \047 or '\'' if you need them:
# 'BEGIN{ ...abc\047def... }'
# 'BEGIN{ ...abc'\''def... }'
scriptText="$1"
shift
fi
# Remaining symbols in "$@" must be data file names and/or variable
# assignments that do not use the "-v name=value" syntax.
if [ -n "${scriptFiles[*]}" ]
then
if (( expandOnly == 1 ))
then
expand_prints "${scriptFiles[@]}"
else
gawk "${awkArgs[@]}" "$(expand_prints "${scriptFiles[@]}")" "$@"
fi
elif [ -n "$scriptText" ]
then
if (( expandOnly == 1 ))
then
printf '%s\n' "$scriptText" | expand_prints
else
gawk "${awkArgs[@]}" "$(printf '%s\n' "$scriptText" |
expand_prints)" "$@"
fi
else
printf '%s: ERROR: no awk script specified.\n' "$toolName" >&2
exit 1
fi
Posted using
www.webuse.net