Home > Archive > Tcl > July 2007 > passing exec a cat, sed and grep command sequence
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 |
passing exec a cat, sed and grep command sequence
|
|
| Andrew Falanga 2007-07-27, 7:10 pm |
| Hi,
>From my bash command line, this works:
cat file | sed 's/^M//g' | grep "^STRING$"
However, when I try to place this in my TCL script, TCL doesn't like
it. I've tried a few variations and a couple of times I actually get
to the point of the command being executed but then sed complains that
it has an unterminated "s" command.
Below is what I've got so far:
% eval [list exec cat file | sed {s/^M//g} | grep ^STRING$]
sed: -e expression #1, char 2: Unterminated `s' command
I saw some earlier postings to this group where eval was used in
conjunction with the list command. I thought, why not, I'll give it a
try. So, how would I actually pass this command to have it work?
Andy
| |
| Larry W. Virden 2007-07-27, 7:10 pm |
| On Jul 27, 10:47 am, Andrew Falanga <af300...@gmail.com> wrote:
>
> cat file | sed 's/^M//g' | grep "^STRING$"
>
> However, when I try to place this in my TCL script, TCL doesn't like
> it.
Well, if you didn't want to turn this into simple Tcl code, you could
always do something like:
exec /bin/sh -c "sed 's/^M//g' < file | grep '^STRING$'"
| |
| Andrew Falanga 2007-07-27, 7:10 pm |
| On Jul 27, 9:01 am, "Larry W. Virden" <lvir...@gmail.com> wrote:
> On Jul 27, 10:47 am, Andrew Falanga <af300...@gmail.com> wrote:
>
>
>
>
> Well, if you didn't want to turn this into simple Tcl code, you could
> always do something like:
>
> exec /bin/sh -c "sed 's/^M//g' < file | grep '^STRING$'"
Thanks. The only reason I'm hesitant to move to simple TCL code
(because honestly, searching for this in TCL wasn't as difficult) is
that this routine belongs in a library and many scripts use this. I'm
afraid that by changing to regexp or something similar in TCL would
perhaps break the scripts.
Andy
| |
| Uwe Klein 2007-07-27, 7:10 pm |
| Andrew Falanga wrote:
> Hi,
>
>
> cat file | sed 's/^M//g' | grep "^STRING$"
>
> However, when I try to place this in my TCL script, TCL doesn't like
> it. I've tried a few variations and a couple of times I actually get
> to the point of the command being executed but then sed complains that
> it has an unterminated "s" command.
>
> Below is what I've got so far:
>
> % eval [list exec cat file | sed {s/^M//g} | grep ^STRING$]
> sed: -e expression #1, char 2: Unterminated `s' command
you are working too hard:
% exec cat file | sed s/^M//g | grep ^STRING\$
returns:
STRING
STRING
STRING
assumed: content of file contains 3 lines with STRING ;-)
G!
uwe
| |
| Andreas Leitgeb 2007-07-27, 7:10 pm |
| Andrew Falanga <af300wsm@gmail.com> wrote:
> cat file | sed 's/^M//g' | grep "^STRING$"
The ^M is actually just one letter, a cr-code, correct?
> However, when I try to place this in my TCL script, TCL doesn't like
> it. I've tried a few variations and a couple of times I actually get
> to the point of the command being executed but then sed complains that
> it has an unterminated "s" command.
> % eval [list exec cat file | sed {s/^M//g} | grep ^STRING$]
> sed: -e expression #1, char 2: Unterminated `s' command
tclsh interprets the ^M as a (mac-)newline, so it actually sees:
eval [list exec cat file | sed {s/
//g} | grep ^STRING$]
While this happens to be ok for tcl, it is not ok for sed
Solution: replace the ^M with e.g. \r
... sed {s/\r//g} ...
Oh, and btw., the eval and list stuff is entirely useless in this
example. the eval+list is (actually was until before new 8.5)
useful only when you need to "splice" a list (e.g. stored in
one variable) into the list of arguments.
Since you have no variable list of arguments, you can just do
set result [exec cat file | sed {s/\r//g} | grep ^STRING$]
You probably want to use exec's result (what grep finally outputs)
or it would be lost forever (well, unless you're *always* doing
that interactively, where the result is echoed back)
Btw., as Larry already answered, doing it all in tcl, rather
than using exec might actually save you some trouble. E.g. if
no such line is found, grep returns a non-zero exit-status
which exec turns into an exception, that you need to catch ...
Tcl's exec could be compared with a swamp: fertile, but dangerous :-)
| |
| Andrew Falanga 2007-07-27, 7:10 pm |
| On Jul 27, 9:15 am, Uwe Klein <uwe_klein_habertw...@t-online.de>
wrote:
> Andrew Falanga wrote:
>
>
>
>
>
>
> you are working too hard:
>
> % exec cat file | sed s/^M//g | grep ^STRING\$
> returns:
> STRING
> STRING
> STRING
> assumed: content of file contains 3 lines with STRING ;-)
>
> G!
> uwe
I tried what you have above and it did not work. I think I know why
and if I was too unclear in my original post, I'm sorry. The "^M" is
not the two characters '^' and 'M', but rather the single character
"Carriage Return", <CR>, "Enter", 0x0d or whatever you prefer to call
it.
Andy
| |
| Andrew Falanga 2007-07-27, 7:10 pm |
| On Jul 27, 9:42 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:
> Andrew Falanga <af300...@gmail.com> wrote:
>
> The ^M is actually just one letter, a cr-code, correct?
>
>
> tclsh interprets the ^M as a (mac-)newline, so it actually sees:
>
> eval [list exec cat file | sed {s/
> //g} | grep ^STRING$]
>
> While this happens to be ok for tcl, it is not ok for sed
>
> Solution: replace the ^M with e.g. \r
> ... sed {s/\r//g} ...
I just figured this out about 5 minutes before reading this post.
Thanks, though. I was trying to do what worked on the command line,
and I had gotten that from a post to comp.unix.shell. It never dawned
on me, until a few minutes ago, to use the escape sequence. The
escape sequence worked just great!
>
> Btw., as Larry already answered, doing it all in tcl, rather
> than using exec might actually save you some trouble. E.g. if
> no such line is found, grep returns a non-zero exit-status
> which exec turns into an exception, that you need to catch ...
Whoever originally wrote this library routine does have it wrapped in
a catch. As I mentioned in my response to Larry, the only reason I'm
working with this exec call is because so many scripts use the
routine. I don't want to break anything. It's honestly a real pain
in the butt. I'd prefer using regexp and since that, like grep, is
all about regular expressions; everything "should" work. However, I
can't tell you the number of times I've been bitten with, "It should
work."
>
> Tcl's exec could be compared with a swamp: fertile, but dangerous :-)
I like this analogy.
Andy
| |
| Uwe Klein 2007-07-27, 7:10 pm |
| Andrew Falanga wrote:
> On Jul 27, 9:15 am, Uwe Klein <uwe_klein_habertw...@t-online.de>
> wrote:
>
>
>
> I tried what you have above and it did not work. I think I know why
> and if I was too unclear in my original post, I'm sorry. The "^M" is
> not the two characters '^' and 'M', but rather the single character
> "Carriage Return", <CR>, "Enter", 0x0d or whatever you prefer to call
> it.
>
> Andy
>
% vi file # added tabs ^T after STRING in 2 of 3 lines
% exec cat file | sed s/\x0d//g | grep ^STRING\$
STRING
% exec cat file | sed s/\t//g | grep ^STRING\$
STRING
STRING
STRING
the thing to keep in mind is that there will be no extra
evaluation by a system shell. So some of the hoops
you try to jump through cary no bonus points.
you can escape any character with \0<octalnumber> or \x<hexnumber>
or \u<unicodehexnumber>
some are predefined in the parser \n \r \t \b ..
seen man tcl:
\a Audible alert (bell) (0x7).
\b Backspace (0x8).
\f Form feed (0xc).
\n Newline (0xa).
\r Carriage-return (0xd).
\t Tab (0x9).
\v Vertical tab (0xb).
\<newline>whiteSpace
A single space character replaces the back-
slash, newline, and all spaces and tabs
after the newline. This backslash sequence
is unique in that it is replaced in a sepa-
rate pre-pass before the command is actually
parsed. This means that it will be replaced
even when it occurs between braces, and the
resulting space will be treated as a word
separator if it isn't in braces or quotes.
\\ Backslash (``'').
\ooo ||
The digits ooo (one, two, or three of them) |
give an eight-bit octal value for the Uni- |
code character that will be inserted. The |
upper bits of the Unicode character will be |
0. |
\xhh ||
The hexadecimal digits hh give an eight-bit |
hexadecimal value for the Unicode character |
that will be inserted. Any number of hex- |
adecimal digits may be present; however, all |
but the last two are ignored (the result is |
always a one-byte quantity). The upper bits |
of the Unicode character will be 0. |
\uhhhh ||
The hexadecimal digits hhhh (one, two, |
three, or four of them) give a sixteen-bit |
hexadecimal value for the Unicode character |
that will be inserted.
Backslash substitution is not performed on words
enclosed in braces, except for backslash-newline as
described above.
uwe
| |
| Cameron Laird 2007-07-27, 7:10 pm |
| In article <1185552482.823173.277330@d30g2000prg.googlegroups.com>,
Andrew Falanga <af300wsm@gmail.com> wrote:
>On Jul 27, 9:42 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
>wrote:
>
>I just figured this out about 5 minutes before reading this post.
>Thanks, though. I was trying to do what worked on the command line,
>and I had gotten that from a post to comp.unix.shell. It never dawned
>on me, until a few minutes ago, to use the escape sequence. The
>escape sequence worked just great!
>
>
>Whoever originally wrote this library routine does have it wrapped in
>a catch. As I mentioned in my response to Larry, the only reason I'm
>working with this exec call is because so many scripts use the
>routine. I don't want to break anything. It's honestly a real pain
>in the butt. I'd prefer using regexp and since that, like grep, is
>all about regular expressions; everything "should" work. However, I
>can't tell you the number of times I've been bitten with, "It should
>work."
>
>
>
>I like this analogy.
| |
| Glenn Jackman 2007-07-27, 10:09 pm |
| At 2007-07-27 10:47AM, "Andrew Falanga" wrote:
> cat file | sed 's/^M//g' | grep "^STRING$"
As others have suggested, this can be rewritten in Tcl. To make it
"library-able" here's a proc (untested):
proc mygrep {filename pattern} {
# replace: cat file | sed 's/^M//g' | grep "^STRING$"
# with:
set results [list]
set fid [open $filename r] ;# may throw an error
while {[gets $fid line] != -1} {
if {[regexp $pattern [string map [list \r ""] $line]} {
lappend results $line
}
}
close $fid
return [join $results \n]
}
set text [mygrep file "^STRING$"]
--
Glenn Jackman
"You can only be young once. But you can always be immature." -- Dave Barry
| |
| Glenn Jackman 2007-07-27, 10:09 pm |
| At 2007-07-27 01:17PM, "Cameron Laird" wrote:
[...][color=darkred]
> While this thread has lost me, I'll assert that the cat is also useless--as
> is the grep.
Indeed: sed -n -e 's/\r//g' -e '/^STRING$/p' file
--
Glenn Jackman
"You can only be young once. But you can always be immature." -- Dave Barry
|
|
|
|
|