Unix Shell - read, printf, and special chars

This is Interesting: Free IT Magazines  
Home > Archive > Unix Shell > December 2006 > read, printf, and special chars





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author read, printf, and special chars
Colin Brace

2006-12-16, 1:19 pm

Hi all,

I've written a simple script to look for a certain pattern in a .cpp
file and comment it out. Here is the main loop:

[...]

exec 3< $FileIn
exec 4> $FileOut

while read LINE <&3 ; do
if [ $(echo $LINE | awk '{print index($LINE,"!cmdline.Found")}') -gt 1
] ; then
printf "%s\n" "//Commented out" >&4
printf "%s %s\n" "//" "$LINE" >&4
for (( i= 1 ; i < 4 ; i++ )) ; do
read 'LINE' <&3
printf "%s %s\n" "//" "$LINE" >&4
done
else
printf "%s\n" "$LINE" >&4
fi
done

[...]

As you can see, when it finds a given pattern, adds a "commented out"
line and comments out that and the subsequent three lines. It works
fine, except for two problems:

1) it strips out leading tabs, ie, indentation
2) it strips out backslashes

A line like this:

printf("myprog OnExit: Terminating core.\n");

gets turned into this:

printf("myprog OnExit: Terminating core.n");

I've tried enclosing the line in single quotes like this:

LINE="'"$LINE"'"

but it doesn't help.

Can someone suggestion a solution?

I realize a shell script isn't the most appropriate tool for reading
and writing to files, but I just need a quick and dirty fix.

Thanks

--
Colin Brace
Amsterdam

Stephane CHAZELAS

2006-12-16, 1:19 pm

2006-12-16, 10:54(-08), Colin Brace:
> Hi all,
>
> I've written a simple script to look for a certain pattern in a .cpp
> file and comment it out. Here is the main loop:
>
> [...]
>
> exec 3< $FileIn
> exec 4> $FileOut
>
> while read LINE <&3 ; do
> if [ $(echo $LINE | awk '{print index($LINE,"!cmdline.Found")}') -gt 1
> ] ; then
> printf "%s\n" "//Commented out" >&4
> printf "%s %s\n" "//" "$LINE" >&4
> for (( i= 1 ; i < 4 ; i++ )) ; do
> read 'LINE' <&3
> printf "%s %s\n" "//" "$LINE" >&4
> done
> else
> printf "%s\n" "$LINE" >&4
> fi
> done

[...]

Ouch. Don't use while read loops, that's bad shell scripting
practice.

awk < "$FileIn" > "$FileOut" '
/.!cmdline\.Found/ {
n = 4
print "//Commented out"
}
n > 0 {
$0 = "// " $0
n--
}
{print}'


Several problems in your script:
- unquoted variables and command substitutions
- usage of read without -r and without modifying IFS
- usage of echo.


--
Stéphane
Colin Brace

2006-12-16, 7:26 pm

On Dec 16, 8:01 pm, Stephane CHAZELAS <this.addr...@is.invalid> wrote:

> Several problems in your script:


> - usage of echo.


St=E9phane, thanks for the quick reply; your awk stuff is very helpful.

Just curious: what do you have against "echo"?

--=20
Colin Brace
Amsterdam

Stephane CHAZELAS

2006-12-17, 1:16 pm

2006-12-16, 11:56(-08), Colin Brace:
> On Dec 16, 8:01 pm, Stephane CHAZELAS <this.addr...@is.invalid> wrote:
>
>
>
> Stéphane, thanks for the quick reply; your awk stuff is very helpful.
>
> Just curious: what do you have against "echo"?

[...]

echo is one of the least reliable and least portable commands.

A UNIX conformant echo (but few echos are) is a command to
expand the \n, \t, \b... escape sequences.

A POSIX conformant echo (UNIX is POSIX, again few (though more)
is a command that outputs its arguments separated by one space
and terminated by a newline character as long as none of them
contains any backslash character and as long as the first
argument is not "-n". Otherwise the behavior is unspecified.

in practice, a Unix echo is a command that outputs its arguments
separated by one space and terminated by a newline character as
long as none of them contains any backslash character and as
long as the first argument does not not start with a "-"
(possibly a "+" as well, and you may have ).

Anyway, even for POSIX and Unix conformant ones, that means that
echo can't be used to display arbitrary data.

POSIX and the Single Unix Specification recommand to use printf
instead.


--
Stéphane
Antonio Maschio

2006-12-18, 1:20 pm

....

and what have you against the while read loops?

-- Antonio
Stephane CHAZELAS

2006-12-18, 1:20 pm

2006-12-18, 14:51(+01), Antonio Maschio:
> ...
>
> and what have you against the while read loops?

[...]

read is a command overloaded to do many things. By default, it
doesn't read a line of input. It should not be seens as an
equivalent of the fgets C library function for instance.

Doing something in a loop in shells means running several
utilities per pass in that loop. You read one line at a time
with the most inappropriate tool (read) and call several
utilities involving pipes and forks for tools that are not meant
to be used that way and that won't even be working
cooperatively.

Text processing in shell is meant to be done in pipelines. You
run one instance of a few tools running concurrently and
cooperatively.

--
Stéphane
Colin Brace

2006-12-18, 7:21 pm

On Dec 18, 6:44 pm, Stephane CHAZELAS <this.addr...@is.invalid> wrote:

> read is a command overloaded to do many things. By default, it
> doesn't read a line of input. It should not be seens as an
> equivalent of the fgets C library function for instance.


Well, it seems you are right. Because I was unable to get awk to do
what I needed it to do, I ended up writing the script in Rexx, which I
should have done in the first place. Among other things, it is now
blindingly fast. All those calls to awk in the read loop must have been
slowing things down terribly as it took about ten seconds to run on a
file of 2100 lines. Now it takes less than a second.

Thanks for the explanation; it was very helpful.

--
Colin Brace
Amsterdam

Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com