-Parag
I mean the output should be on the same line
ot separate lines
Not natively, without the usual caveats.
The simplest is:
for (i=2; i<NF; i++)
printf("%s ",$i)
print $i
I will leave it to others to point out where/why the above may be
sub-optimal, and what other approaches exist.
> hi All,
> is there anyway to print the fields 2 to end of the line?
A loop is a common way (although sometimes not optimal):
$ echo "1 2 3 4 5 6" | \
awk '{for (i=2; i<=NF; i++) { printf("%s ", $i)} printf("\n")}'
2 3 4 5 6
Note that this leaves a space at the end. Moreover, it does not preserve
original spacing between fields.
Another way could be this:
$ echo "1 2 3 4 5 6" | awk '{$1=""; sub(/^[[:space:]]*/,""); print}'
2 3 4 5 6
which, again, does not preserve original spacing.
Assuming default field separator, you could also match the first field and
then remove it (this preserves original spacing):
$ echo "1 2 3 4 5 6" | \
awk '{match($0,/[^[:space:]]+[[:space:]]*/); print substr($0,RLENGTH+1)}'
2 3 4 5 6
If your input lines have spaces before any nonspace character, then the
above regular expression must be modified to account for that, ie
$ echo " 1 2 3 4 5 6" | \
awk '{match($0,/[[:space:]]*[^[:space:]]+[[:space:]]*/); print
substr($0,RLENGTH+1)}'
2 3 4 5 6
which is more general.
There might be better methods, of course. I'm not an awk guru at all.
Hope this helps.
> is there anyway to print the fields 2 to end of the line?
If you're not too fussed about the extra whitespace, you may like
{ $1=""; print }
Cheers,
- Joel
awk 'sub(/^[[:space:]]*[^[:space:]]*[[:space:]]*/,"")1' file
In general with GNU awk (gawk) or any other awk that supports RE intervals and
assuming your field separator is white space:
gawk --re-interval 'sub(/^[[:space:]]*([^[:space:]]*[[:space:]]*){N}/,"")1' file
Replace "N" with the number of fields to delete.
Regards,
Ed.
On 3/3/2008 6:20 AM, pk wrote:
> parag...@hotmail.com wrote:
>
>
>>hi All,
>>is there anyway to print the fields 2 to end of the line?
>
>
> A loop is a common way (although sometimes not optimal):
>
> $ echo "1 2 3 4 5 6" | \
> awk '{for (i=2; i<=NF; i++) { printf("%s ", $i)} printf("\n")}'
Normally you'd just use
.... print ""
instead of:
.... printf("\n")
as it's shorter and uses the ORS value. Technically you should really use:
for (i=2; i<NF; i++) {printf "%s%s",$i,OFS} print $NF
so you use the OFS too and avoid adding a trailing blank at the end of each
record. Also note that print and printf are language constructs, not functions
so the use of "(" and ")" is incorrect/misleading and while they won't do any
hamr most of the time they can produce some unexpected results, e.g.:
$ awk 'BEGIN{printf("%s\n"),"foo"}'
foo
> 2 3 4 5 6
>
> Note that this leaves a space at the end. Moreover, it does not preserve
> original spacing between fields.
>
> Another way could be this:
>
> $ echo "1 2 3 4 5 6" | awk '{$1=""; sub(/^[[:space:]]*/,""); print}'
> 2 3 4 5 6
>
> which, again, does not preserve original spacing.
>
> Assuming default field separator, you could also match the first field and
> then remove it (this preserves original spacing):
>
> $ echo "1 2 3 4 5 6" | \
> awk '{match($0,/[^[:space:]]+[[:space:]]*/); print substr($0,RLENGTH+1)}'
> 2 3 4 5 6
>
> If your input lines have spaces before any nonspace character, then the
> above regular expression must be modified to account for that, ie
>
> $ echo " 1 2 3 4 5 6" | \
> awk '{match($0,/[[:space:]]*[^[:space:]]+[[:space:]]*/); print
> substr($0,RLENGTH+1)}'
> 2 3 4 5 6
You can just use sub() instead of match()+substr().
Ed.
> Normally you'd just use
>
> .... print ""
>
> instead of:
>
> .... printf("\n")
>
> as it's shorter and uses the ORS value. Technically you should really use:
>
> for (i=2; i<NF; i++) {printf "%s%s",$i,OFS} print $NF
>
> so you use the OFS too and avoid adding a trailing blank at the end of
> each record.
Thanks. I was suspecting I was overlooking some technicalities.
> Also note that print and printf are language constructs, not
> functions so the use of "(" and ")" is incorrect/misleading and while they
> won't do any hamr most of the time they can produce some unexpected
> results, e.g.:
>
> $ awk 'BEGIN{printf("%s\n"),"foo"}'
> foo
Ok. But why is the above "unexpected result"? It just prints "foo" and a
newline, as per the "%s\n" format string. Removing the "(" and ")" produces
the same output.
> You can just use sub() instead of match()+substr().
Correct. I just overlooked it in favour of a more complex solution.
Thanks!
On 3/3/2008 7:09 AM, pk wrote:
> Ed Morton wrote:
>
>
>>Normally you'd just use
>>
>>.... print ""
>>
>>instead of:
>>
>>.... printf("\n")
>>
>>as it's shorter and uses the ORS value. Technically you should really use:
>>
>>for (i=2; i<NF; i++) {printf "%s%s",$i,OFS} print $NF
>>
>>so you use the OFS too and avoid adding a trailing blank at the end of
>>each record.
>
>
> Thanks. I was suspecting I was overlooking some technicalities.
>
>
>>Also note that print and printf are language constructs, not
>>functions so the use of "(" and ")" is incorrect/misleading and while they
>>won't do any hamr most of the time they can produce some unexpected
>>results, e.g.:
>>
>>$ awk 'BEGIN{printf("%s\n"),"foo"}'
>>foo
>
>
> Ok. But why is the above "unexpected result"?
Because if the "(" and ")" meant what they appear to (i.e. function parameter
delimiters) then the above should produce an error message as it's clearly a
typo. Look how a function (sprintf()) behaves in the same situation:
$ awk 'BEGIN{ printf("%s\n"),"a" }'
a
$ awk 'BEGIN{ print sprintf("%s\n"),"a" }'
awk: fatal: not enough arguments to satisfy format string
`%s
'
^ ran out for this one
> It just prints "foo" and a
> newline, as per the "%s\n" format string. Removing the "(" and ")" produces
> the same output.
Precisely the problem.
>
>>You can just use sub() instead of match()+substr().
>
>
> Correct. I just overlooked it in favour of a more complex solution.
>
> Thanks!
>
You're welcome.
Ed.
>>>$ awk 'BEGIN{printf("%s\n"),"foo"}'
>>>foo
>>
>>
>> Ok. But why is the above "unexpected result"?
>
> Because if the "(" and ")" meant what they appear to (i.e. function
> parameter delimiters) then the above should produce an error message as
> it's clearly a typo.
Ah ok, now I see. I wasn't realizing that the absence of errors *is* the
unexpected result.
Thanks again!
I think your argument is a little twisted here. I don't think there is
any requirement that an implementation produce a diagnostic for this
case, though I admit that every AWK I tested on (just now), except, of
course, for Solaris old AWK, did produce a fatal error (for sprintf, and
not for printf). In general, relying on the implementation to assist in
situations like this is not in the "spirit of C".
There is, of course, another (well known) case where *failure* to
parenthesize causes unexpected behavior, so it is at best a wash.
You might like to check out a thread over in clc (my favorite newsgroup)
about whether or not the sizeof operator should parenthesize its
argument. Very similar - in that those arguing against it (i.e.,
arguing for: sizeof x
instead of: sizeof(x)
) have little on their side other than "It looks better to *me* that way".
Needless to say, in that thread, my sentiments are with Richard Riley -
who argues well that the parens are a good idea, though technically not
required.
I don't have the thread title at hand - as is usual for clc, it was
something dumb, like "function" or something like that. The threads
there always start out with some dumb newbie question, then get taken
over by flame wars among the regulars (and irregulars). You can
probably find it via Google for by searching for posts by de...@gmail.com.
As I pointed out, relying on diagnostics is not in the spirit of C and
C-like languages. It is not a good habit to get into.
>>Ah ok, now I see. I wasn't realizing that the absence of errors *is* the
>>unexpected result.
>>
>>Thanks again!
>
> As I pointed out, relying on diagnostics is not in the spirit of C and
> C-like languages. It is not a good habit to get into.
Agreed. Actually, my habit of putting parenthesis around arguments to printf
in awk comes from C.
What I was missing was the crucial fact that, unlike C, in awk printf is NOT
a function, but an I/O statement, and as such does not require parenthesis.
I'm not expecting awk to emit any kind of warning when unneeded parenthesis
are used, if nothing else because sometimes parenthesis are needed to
disambiguate. Knowing that printf is not a function helps me avoiding
unneeded parenthesis.
On 3/3/2008 7:51 AM, Kenny McCormack wrote:
> In article <47CBF98...@lsupcaemnt.com>,
> Ed Morton <mor...@lsupcaemnt.com> wrote:
> ...
>
>>>>Also note that print and printf are language constructs, not
>>>>functions so the use of "(" and ")" is incorrect/misleading and while they
>>>>won't do any hamr most of the time they can produce some unexpected
>>>>results, e.g.:
>>>>
>>>>$ awk 'BEGIN{printf("%s\n"),"foo"}'
>>>>foo
>>>
>>>
>>>Ok. But why is the above "unexpected result"?
>>
>>Because if the "(" and ")" meant what they appear to (i.e. function parameter
>>delimiters) then the above should produce an error message as it's clearly a
>>typo. Look how a function (sprintf()) behaves in the same situation:
>
>
> I think your argument is a little twisted here. I don't think there is
> any requirement that an implementation produce a diagnostic for this
> case, though I admit that every AWK I tested on (just now), except, of
> course, for Solaris old AWK, did produce a fatal error (for sprintf, and
> not for printf). In general, relying on the implementation to assist in
> situations like this is not in the "spirit of C".
It's not about relying on...., it's just about writing clear, accurate software
vs misleading software that can have unexpected results.
> There is, of course, another (well known) case where *failure* to
> parenthesize causes unexpected behavior, so it is at best a wash.
Could you provide that example as I'm not familiar with it?
<OT>
> You might like to check out a thread over in clc (my favorite newsgroup)
> about whether or not the sizeof operator should parenthesize its
> argument. Very similar - in that those arguing against it (i.e.,
> arguing for: sizeof x
> instead of: sizeof(x)
> ) have little on their side other than "It looks better to *me* that way".
sizeof x is for objects (variables)
In "sizeof (x)" where x is a type, (x) effectively creates an object of the type
x and then sizeof operates on that object to get it's size.
> Needless to say, in that thread, my sentiments are with Richard Riley -
> who argues well that the parens are a good idea, though technically not
> required.
They are required for types but they aren't surrounding function arguments,
they're just creating something that the sizeof operator can work on. For
variables they're misleading and redundant at best.
> I don't have the thread title at hand - as is usual for clc, it was
> something dumb, like "function" or something like that. The threads
> there always start out with some dumb newbie question, then get taken
> over by flame wars among the regulars (and irregulars). You can
> probably find it via Google for by searching for posts by de...@gmail.com.
I'm not going to look at CLC due to lack of interest and all the usual reasons
to avoid CLC. You could point out that many people use:
return(value);
instead of:
return value;
but I still don't think it's relevant to whether or not their use in prints is a
good idea...
</OT>
Ed.
$ echo "a b c d e f" | read skip rest ; echo "$rest"
b c d e f
Or, if your shell requires brackets...
$ echo "a b c d e f" | { read skip rest ; echo "$rest" ;}
b c d e f
Janis
>
> -Parag
> On 3/3/2008 5:00 AM, parag...@hotmail.com wrote:
>>
>> is there anyway to print the fields 2 to end of the line?
>>
> awk 'sub(/^[[:space:]]*[^[:space:]]*[[:space:]]*/,"")1' file
What is the function of the number "1" in the above statement? I tried
this both with and without the "1" and it seems to produce the same
results. Just at a glance, it actually looks like a syntax error to me,
although awk obviously doesn't think it is. :-)
Could you please explain?
Thank you!
--
Conrad J. Sabatier <con...@cox.net>
"Procrastinate now; don't put it off." -- Ellen Degeneres
It produces only the same results if substitutions have taken
place on a line; other lines will not be printed.
> Just at a glance, it actually looks like a syntax error to me,
> although awk obviously doesn't think it is. :-)
It isn't a syntax error.
>
> Could you please explain?
sub() returns the number of substitutions, that number is
implicitly taken as a string, concatenated with the 1 which
is also implicitly converted to a string, then interpreted
as a number, which finally is taken as a condition ('true'
in this case of adding a '1') for the default action print.
I find this pattern not very intuitive.
Conceptually you may find this one more comprehensive (I do)...
awk 'sub(/^[[:space:]]*[^[:space:]]*[[:space:]]*/,"") || 1' file
Janis
>
> Thank you!
>
> --
> Conrad J. Sabatier <conr...@cox.net>
On 3/4/2008 3:42 AM, Conrad J. Sabatier wrote:
> On Mon, 03 Mar 2008 06:26:18 -0600, Ed Morton wrote:
>
>
>>On 3/3/2008 5:00 AM, parag...@hotmail.com wrote:
>>
>>>is there anyway to print the fields 2 to end of the line?
>>>
>>
>>awk 'sub(/^[[:space:]]*[^[:space:]]*[[:space:]]*/,"")1' file
>
>
> What is the function of the number "1" in the above statement? I tried
> this both with and without the "1" and it seems to produce the same
> results. Just at a glance, it actually looks like a syntax error to me,
> although awk obviously doesn't think it is. :-)
>
> Could you please explain?
The body of an awk program consists of:
<condition> { <action> }
segments, where the <condition> is tested for every record in the input
file and if found to be true the <action> is performed. Both the <condition>
and the <action> are optional. If no <condition> is specified then the
default of "true" is applied and <action> is executed. If no <action> is
specified then the default of "print $0" is executed.
In this script:
awk 'sub(...)1' file
we're only specifying the <condition> part of the awk body, it just happens to
invoke sub() and test it's result as part of that <condition>. So, if sub()
returns a non-zero value then the <condition> is true, but if sub() returns zero
(as would happen if the input record was empty or otherwise did not contain a
string to match the RE using as the first sub() argument, then sub() would
return zero and so, if not for the "1" at the end, the overall condition would
be false and so no output would be produced.
You can actually use any number or string in place of "1" since whatever you put
there will be string-concatenated with the result of the sub() and then
string-compared with the null string to determine if the condition is true or
false, so these are all equivalent:
awk 'sub(...)1' file
awk 'sub(...)999' file
awk 'sub(...)0' file
awk 'sub(...)"non-null string"' file
It's a common awk idiom and you'll never forget it now you've seen it, but if
you don't like it you can use the explicit:
awk '{sub(...); print}' file
Regards,
Ed.
On 3/4/2008 5:10 AM, Janis wrote:
> On 4 Mrz., 10:42, "Conrad J. Sabatier" <conr...@cox.net> wrote:
>
>>On Mon, 03 Mar 2008 06:26:18 -0600, Ed Morton wrote:
>>
>>>On 3/3/2008 5:00 AM, parag_p...@hotmail.com wrote:
>>
>>>>is there anyway to print the fields 2 to end of the line?
>>>
>>>awk 'sub(/^[[:space:]]*[^[:space:]]*[[:space:]]*/,"")1' file
>>
>>What is the function of the number "1" in the above statement? I tried
>>this both with and without the "1" and it seems to produce the same
>>results.
>
>
> It produces only the same results if substitutions have taken
> place on a line; other lines will not be printed.
>
>
>> Just at a glance, it actually looks like a syntax error to me,
>>although awk obviously doesn't think it is. :-)
>
>
> It isn't a syntax error.
>
>
>>Could you please explain?
>
>
> sub() returns the number of substitutions, that number is
> implicitly taken as a string, concatenated with the 1 which
> is also implicitly converted to a string, then interpreted
> as a number,
No, it's just 2 numbers (the sub() return and 1) which get string-concatenated
to form a string which is then compared to the null string. The resulting string
doesn't get interpreted as a number (try it with zero instead of 1).
Yes, until here that's what I said (or at least what I intended to
express by my words).
> which is then compared to the null string. The resulting string
> doesn't get interpreted as a number (try it with zero instead of 1).
No, I think you are not correct. And here's my try...
$ echo X | awk 'sub(/A/,"B")1'
X
$ echo X | awk 'sub(/A/,"B")0'
$ echo A | awk 'sub(/A/,"B")1'
B
$ echo A | awk 'sub(/A/,"B")0'
B
You see, in case that there's no match, nothing is printed.
Janis
>
>
>
> > which finally is taken as a condition ('true'
> > in this case of adding a '1') for the default action print.
>
> > I find this pattern not very intuitive.
>
> > Conceptually you may find this one more comprehensive (I do)...
>
> > awk 'sub(/^[[:space:]]*[^[:space:]]*[[:space:]]*/,"") || 1' file
>
> > Janis
>
> >>Thank you!
>
> >>--
> >>Conrad J. Sabatier <conr...@cox.net>
>
> >>"Procrastinate now; don't put it off." -- Ellen Degeneres- Zitierten Text ausblenden -
>
> - Zitierten Text anzeigen -- Zitierten Text ausblenden -
>
> - Zitierten Text anzeigen -
Interesting. That seems to be a peculiarity of /usr/xpg4/bin/awk on Solaris:
$ echo X | nawk 'sub(/A/,"B")0'
X
$ echo X | gawk 'sub(/A/,"B")0'
X
$ echo X | /usr/xpg4/bin/awk 'sub(/A/,"B")0'
$
I can see absolutely no reason why the string "00" should be converted to a
number for testing in the condition. Look at this too:
$ echo X | nawk '"0"'
X
$ echo X | gawk '"0"'
X
$ echo X | gawk --posix '"0"'
X
$ echo X | /usr/xpg4/bin/awk '"0"'
$
I think that's a bug in /usr/xpg4/bin/awk.
Regards,
Ed.
Hmmmm... Version of AWK?
I just tested with every version of AWK I have access to (including TAWK)
and they all print "X" for your second example above (*). Changing it to:
echo X | awk '(sub(/A/,"B")0)+0'
has, of course, the expected effect.
(*) Except, of course, for Solaris old AWK, in which it is, surprise,
surprise, a syntax error.
Yes, good point. That's the one I didn't test.
I'm currently using the awk available with MKS. There's no
specific version information but the man page claims...
PORTABILITY
POSIX.2. x/OPEN Portability Guide 4.0. All UNIX systems. Windows
95/98/Millennium. Windows NT 4.0. Windows 2000.
[...]
Anyway. I want to emphasize that such constructs like "sub(...)1"
with non-apparent/"invisible" _implicit castings_ are not a pattern
one should suggest to use. There are conceptually clearer ways to
express the intention of the code upthread; in the "worst" case,
to prevent problems, one can fall back to a more conservative
awk '{sub(/^[[:space:]]*[^[:space:]]*[[:space:]]*/,"");print}' file
in case one dislikes a form without type conversions like...
awk 'sub(/^[[:space:]]*[^[:space:]]*[[:space:]]*/,"")||1' file
Janis
>
Or meet somewhere half-way (between a fully explicit expression
and most terse idiom) with
awk '{sub(...)}1' file
(which has the property to avoid the implicit castings as well,
and seems to be unambiguously valid WRT xpg4 or MKS's POSIX awk).
Janis
This is equivalent to (and the same # of characters as): sub(...)||1
And I, speaking only of personal aesthetics, think that's actually best.
I think this all started sometime back (in c.l.a.) when we had a little
contest to see what was the least typing, and somebody worked out the
version with the implicit string concatenation. It *is* the shortest,
but maybe not the best.
I could live with that since it's a bit clearer and avoids the problems with
those 2 awks. I'll try to start using it. I used to, then at some point got
converted to the dark side....
Ed.