|
|
|
|
||||||
| comp.unix.shell Using and programming the Unix shell. |
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
I've got a multi pipe command that includes an awk print. I have 7
fields, I'd like to NOT print fields 3 and 7. For something this simple I realize I could simply print 1,2,4,5, and 6 but there will be times later when the field count could be as high as 14 and some of the lines may not have exactly 14 fields, but I will never want fields 3 and 7. In laymens terms I'd like it to do this: blah | blah | blah | awk `!{print $3,$7}` | blah Thanks. ~F |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
Faeandar wrote:
> I've got a multi pipe command that includes an awk print. I have 7 > fields, I'd like to NOT print fields 3 and 7. > > For something this simple I realize I could simply print 1,2,4,5, and > 6 but there will be times later when the field count could be as high > as 14 and some of the lines may not have exactly 14 fields, but I will > never want fields 3 and 7. > > In laymens terms I'd like it to do this: > > blah | blah | blah | awk `!{print $3,$7}` | blah If you don't care about the effect on white space between fields, then all you need to do is empty the fields you don't care about: blah | awk '{$3=$7=""}1' | blah Otherwise, if your awk supports RE intervals, here's how to delete all fields up to field N, preserving input formatting (gawk example): gawk --re-interval 'sub(/^[[:space:]]*([^[:space:]]*[[:space:]]*){1}/,"")' gawk --posix '...' The number within the "{...}" is the number of initial fields to delete. Note that "gensub()" is not available with "--posix" but it is available with "--re-interval" so if you need to use an interval expression (e.g. {1,} or {8} or {2,4}) with gensub() then you must use --re-interval rather than --posix so --re-interval is generally the preferred method. Mofdify the above to suit. If you're going to do that, though, you might as well use the equivalent sed command. Regards, Ed. |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
On Mon, 23 Jul 2007 00:30:18 -0500, Ed Morton <morton@lsupcaemnt.com>
wrote: >Faeandar wrote: >> I've got a multi pipe command that includes an awk print. I have 7 >> fields, I'd like to NOT print fields 3 and 7. >> >> For something this simple I realize I could simply print 1,2,4,5, and >> 6 but there will be times later when the field count could be as high >> as 14 and some of the lines may not have exactly 14 fields, but I will >> never want fields 3 and 7. >> >> In laymens terms I'd like it to do this: >> >> blah | blah | blah | awk `!{print $3,$7}` | blah > >If you don't care about the effect on white space between fields, then >all you need to do is empty the fields you don't care about: > >blah | awk '{$3=$7=""}1' | blah > >Otherwise, if your awk supports RE intervals, here's how to delete all >fields up to field N, preserving input formatting (gawk example): > >gawk --re-interval 'sub(/^[[:space:]]*([^[:space:]]*[[:space:]]*){1}/,"")' >gawk --posix '...' > >The number within the "{...}" is the number of initial fields to delete. >Note that "gensub()" is not available with "--posix" but it is available >with "--re-interval" so if you need to use an interval expression (e.g. >{1,} or {8} or {2,4}) with gensub() then you must use --re-interval >rather than --posix so --re-interval is generally the preferred method. > >Mofdify the above to suit. If you're going to do that, though, you might >as well use the equivalent sed command. > >Regards, > > Ed. What you just explained is going to take some research on my part just to understand it, but you've given me a direction to at least look. Thank you. Out of curiosity, what is the equivalent sed command and why might I as well use it instead of awk? Thanks. ~F |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On Mon, 23 Jul 2007 00:47:13 -0700, Faeandar wrote:
> On Mon, 23 Jul 2007 00:30:18 -0500, Ed Morton <morton@lsupcaemnt.com> > wrote: > >>Faeandar wrote: >>> I've got a multi pipe command that includes an awk print. I have 7 >>> fields, I'd like to NOT print fields 3 and 7. >>> >>> For something this simple I realize I could simply print 1,2,4,5, and >>> 6 but there will be times later when the field count could be as high >>> as 14 and some of the lines may not have exactly 14 fields, but I will >>> never want fields 3 and 7. >>> >>> In laymens terms I'd like it to do this: >>> >>> blah | blah | blah | awk `!{print $3,$7}` | blah >> >>If you don't care about the effect on white space between fields, then >>all you need to do is empty the fields you don't care about: >> >>blah | awk '{$3=$7=""}1' | blah >> >>Otherwise, if your awk supports RE intervals, here's how to delete all >>fields up to field N, preserving input formatting (gawk example): >> >>gawk --re-interval >>'sub(/^[[:space:]]*([^[:space:]]*[[:space:]]*){1}/,"")' gawk --posix >>'...' >> >>The number within the "{...}" is the number of initial fields to delete. >>Note that "gensub()" is not available with "--posix" but it is available >>with "--re-interval" so if you need to use an interval expression (e.g. >>{1,} or {8} or {2,4}) with gensub() then you must use --re-interval >>rather than --posix so --re-interval is generally the preferred method. >> >>Mofdify the above to suit. If you're going to do that, though, you might >>as well use the equivalent sed command. >> >>Regards, >> >> Ed. > > What you just explained is going to take some research on my part just > to understand it, but you've given me a direction to at least look. > Thank you. > > Out of curiosity, what is the equivalent sed command and why might I as > well use it instead of awk? > I suppose this (one line) is approx. along the line of Ed. advice: $ echo "one two three four five six seven and seven is" | sed 's/\([^[:space:]]*\) \([^[:space:]]*\) \([^[:space:]]*\) \([^[:space:]]*\) \([^[:space:]]*\) /\1 \2 \4 /' one two four six seven and seven is There are possibilities to make it more condensed but I think for this kind of case that's clearer to start with a visually direct expression :-) I'd say you might as well use it instead of 'awk' because it'll work as is in 'sed', without needing a special trigger or a specific awk and using a rare function in it, on the other side 'sed' was almost build for this use :-) |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
In article <YfednaeGI6JyoTnbnZ2dnUVZ_uGknZ2d@comcast.com>,
Ed Morton <morton@lsupcaemnt.com> wrote: .... >If you don't care about the effect on white space between fields, then >all you need to do is empty the fields you don't care about: > >blah | awk '{$3=$7=""}1' | blah > >Otherwise, if your awk supports RE intervals, here's how to delete all >fields up to field N, preserving input formatting (gawk example): > >gawk --re-interval 'sub(/^[[:space:]]*([^[:space:]]*[[:space:]]*){1}/,"")' >gawk --posix '...' Isn't it simpler (conceptually, but not in the 'golf' sense) to just do a loop? Gives you more control over the output. Something like (and, yes, there are several variations on this, depending on your mood and/or the phase of the moon - use this only as an example): for (i=1; i<=NF; i++) if (i != 3 && i != 7) printf("%s%s",$i,i < NF ? " " : "\n") (Yes, there could be an issue if NF == 7; left as exercise for the reader) |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
Kenny McCormack wrote:
> In article <YfednaeGI6JyoTnbnZ2dnUVZ_uGknZ2d@comcast.com>, > Ed Morton <morton@lsupcaemnt.com> wrote: > ... > >>If you don't care about the effect on white space between fields, then >>all you need to do is empty the fields you don't care about: >> >>blah | awk '{$3=$7=""}1' | blah >> >>Otherwise, if your awk supports RE intervals, here's how to delete all >>fields up to field N, preserving input formatting (gawk example): >> >>gawk --re-interval 'sub(/^[[:space:]]*([^[:space:]]*[[:space:]]*){1}/,"")' >>gawk --posix '...' > > > Isn't it simpler (conceptually, but not in the 'golf' sense) to just do > a loop? Gives you more control over the output. Something like (and, > yes, there are several variations on this, depending on your mood and/or > the phase of the moon - use this only as an example): > > for (i=1; i<=NF; i++) > if (i != 3 && i != 7) > printf("%s%s",$i,i < NF ? " " : "\n") > > (Yes, there could be an issue if NF == 7; left as exercise for the reader) > That'd also change the white space between fields, so you may as well just do $3=$7="". Ed. |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
In article <dia8a3ldfm3n7j6v2fl3f0q72qep3u23q3@4ax.com>,
Faeandar <mr_castalot@yahoo.com> wrote: >I've got a multi pipe command that includes an awk print. I have 7 >fields, I'd like to NOT print fields 3 and 7. > >For something this simple I realize I could simply print 1,2,4,5, and >6 but there will be times later when the field count could be as high >as 14 and some of the lines may not have exactly 14 fields, but I will >never want fields 3 and 7. > >In laymens terms I'd like it to do this: > >blah | blah | blah | awk `!{print $3,$7}` | blah > >Thanks. > >~F A number of things come to mind. none are particularly 'elegant', but all will 'get the job done'. 1) if you refer to a field that does not exist, it (and any others past the original 'last field' in the record) will be created and set to a null value. Thus you could simply itemize out to field 14, and you'll just get extra trailing white-space when the input record is less than 14 fields. 2) you can print individual fields with separate "printf" statements, without causing them to be separate output 'records'. by making the execution of the printf conditional on NF being at least as big as the field it would be printing, you can get 'exactly' the fields you want, with no trailing gubbage. of course you have to unconditionally 'printf' a record-separator at the end of the 'conditional printf' list. 3) variation on the above, copy first field into 'output' variable. for fields 2, 4, 5, 6 append the output separator to the 'output' variable, and then the indicate field. then for fields 8 to NF, do the same thing. Then print the output variable. 4) you could save 'NF', do an 'offset copy' of the fields of interest (e.g. copy field 4 into field 3, field 5 into field 4, 6 into 5, 8 into 6, 9 into 7, etc, through 14 into 12, decrement the 'saved' NF value by 2, shove it back into NF, and print the record. 5) the _dirty_ way is to do the deed in two parts: (a) simply set fields 3 and 7 to a _fixed_ 'unique' identifier that you can guarantee will never appear in the data (b) 'post-process' the awk output to remove the sequence that is "{field_separator}{unique_value}" the whole thing can be conceptually as simple as: awk -e '{ $3="\b";$7="\b" rint; }' | sed -e '1,$s/ \b//g'(note; untested! quoting and escaping may need to be tweaked) 6) an alternative to 5), above, is to null the fields and then 'gsub()' the entire record to suppress the spurious fields before printing, instead of using the additional sed process. |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
On Mon, 23 Jul 2007 04:15:16 +0000, Faeandar wrote:
> I've got a multi pipe command that includes an awk print. I have 7 > fields, I'd like to NOT print fields 3 and 7. > > For something this simple I realize I could simply print 1,2,4,5, and 6 > but there will be times later when the field count could be as high as > 14 and some of the lines may not have exactly 14 fields, but I will > never want fields 3 and 7. > > In laymens terms I'd like it to do this: > > blah | blah | blah | awk `!{print $3,$7}` | blah > > Thanks. > > ~F If you are not worried about spacing, just set the fields to the empty string. awk '{$3=""; $7="" ; print}' It may be that "cut" is a better choice for this kind of problem. cut -f1-2,4-6,8- |
|
![]() |
| Outils de la discussion | |
|
|