How to remove mth and nth column from a file?


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting How to remove mth and nth column from a file?
# 8  
Old 08-06-2013
Try this:
Code:
awk -F, '{sub($a FS,x)} sub($(b-1) FS,x)' a=7 b=12 file

# 9  
Old 08-06-2013
Should work without brackets too
awk -F, 'sub($a FS,x) sub($(b-1) FS,x)' a=7 b=12 file

This works by changing the column and its filed separator $a FS to x
Since x is not defined, it will be blank.
# 10  
Old 08-06-2013
This is done.. Thanks Everybody for your helps
# 11  
Old 08-06-2013
Or you can use cut
Code:
m=7
n=12
cut -d, --complement -s -f$m,$n file

This User Gave Thanks to Jotne For This Post:
# 12  
Old 08-06-2013
Quote:
Originally Posted by Jotne
This should do it
Code:
awk -F, '{$a=$b="";gsub(FS "+",FS)} 1' a=$m b=$n OFS=, df_test_removing_column

The first and last columns won't have an extra pair of comma if they are deleted so FS "+" would not work. Also if one column was originally empty that column would also be deleted. It's better to just use split and array looping instead:
Code:
awk -v m=3 -v n=9 -- '{
    last = split($0, a, /,/)
    append = 0
    for (i = 1; i < last; ++i) {
        if (i != m && i != n) {
            if (append) {
                printf "," a[i]
            } else {
                printf a[i]
                append = 1
            }
        }
    }
    print ""
}' file

Or
Code:
awk -v m=3 -v n=9 -- '{ last = split($0, a, /,/); append = 0; for (i = 1; i < last; ++i) { if (i != m && i != n) { if (append) { printf "," a[i]; } else { printf a[i]; append = 1; }; }; } print ""; }' file

If we use bash for the shell it could be simpler:
Code:
#!/bin/bash

function remove_columns {
    local A LINE IFS=,
    while read -ra LINE; do
        for A; do
            unset "LINE[$A]"
        done
        echo "${LINE[*]}"
    done
}

remove_columns "$m" "$n" < file  ## could be more than two columns specified

# 13  
Old 08-06-2013
Quote:
Originally Posted by Franklin52
Try this:
Code:
awk -F, '{sub($a FS,x)} sub($(b-1) FS,x)' a=7 b=12 file

Quote:
Originally Posted by Jotne
Should work without brackets too
awk -F, 'sub($a FS,x) sub($(b-1) FS,x)' a=7 b=12 file

This works by changing the column and its filed separator $a FS to x
Since x is not defined, it will be blank.
These suggestions should not be trusted for a moment. Blindly treating literal text data as regular expressions is asking for trouble. Both sub($a FS, x) and sub($(b-1) FS, x) are problematic in multiple respects.

If that text contains a regular expression metacharacter, who knows where in $0 and how much of $0 it will match.

Even if there are no metacharacters, neither substitution is guaranteed to occur at the correct field; if a preceding field matches the regular expression, that earlier field takes precedence. For example, if a is 5, nothing prevents $5 FS from matching at any point between $1 and $5 inclusive.

If there are metacharacters, the situation is worse, because then a literal string when treated as a regular expression may not even match itself. For example, both of the following expressions are false: "(1)" FS ~ "(1)" FS and "[a]" FS ~ "[a]" FS. This means that for a=5 $5 FS may not match itself but it could match at some other location, both before or after $5.

In Franklin52's code, since the numeric return value of sub($(b-1) FS,x) evaluated in a boolean context controls printing, and since (as just pointed out) literal text as a regular expression may not match itself, entire records could be silently deleted if the controlling sub makes no substitutions.

In Jotne's version, the two numeric return values are converted to strings, concatenated, and the result is evaluated in a boolean context. Since there will always be a numeric return value, and since no number converts to a null string, the string which is evaluated in a boolean context is never empty and so is always true. Even if there were no other problems with the code, I would recommend against this because of the subtlety involved. The chances are extremely high that whoever inherits this code will not fully understand it.

Finally, there's also the possibility that the text is an undefined regular expression, which could produce different output on different awk implementations given identical input.



Quote:
Originally Posted by Jotne
Or you can use cut
Code:
m=7
n=12
cut -d, --complement -s -f$m,$n file

Great solution, so long as portability isn't a concern.

If portability is a constraint, --complement is disallowed. In which case using cut would require constructing the -f option-argument from $m and $n, yielding something similar to 1-($m-1),($m+1)-($n-1),($n+1)-. However, the logic required to properly handle all boundary conditions isn't worth the trouble when there's a simple, portable AWK solution available (presented below).



Quote:
Originally Posted by konsolebox
It's better to just use split and array looping instead:
Code:
awk -v m=3 -v n=9 -- '{
    last = split($0, a, /,/)
    append = 0
    for (i = 1; i < last; ++i) {
        if (i != m && i != n) {
            if (append) {
                printf "," a[i]
            } else {
                printf a[i]
                append = 1
            }
        }
    }
    print ""
}' file

I agree with you that the best (only?) AWK solution is to iterate over the fields, excluding the undesirables. It is a robust approach that's immune to all the problems arising from treating literal text as regular expressions.

I did not test your code, but looking at it there appears to be an off-by-one bug at i < last. last corresponds to the final field and it is never printed. It should be i <= last.

Aside from that, your implementation is also a bit overcomplicated. There is no need to explicitly split the record into an array when AWK has already split it into field variables for your convenience.

For portability, simplicty, and flexibility, I recommend:
Code:
{
    for (i=1; i<=NF; i++)
        if (i != m  &&  i != n)
            s = s OFS $i
    print substr(s, length(OFS)+1)
    s=""
}

Obviously, FS and OFS must be set to the appropriate values.



Quote:
Originally Posted by zaq1xsw2
This is done.. Thanks Everybody for your helps
For the sake of those who follow in your footsteps, seeking a solution to an identical or similar problem, the least you can do is state how you solved your problem. This is especially true if all the suggestions provided to you were inadequate and you either crafted your own approach or found one elsewhere.

Regards,
Alister

Last edited by alister; 08-06-2013 at 06:55 PM..
These 2 Users Gave Thanks to alister For This Post:
# 14  
Old 08-06-2013
Another formatting trick
Code:
{
  sep=""
  for (i=1; i<=NF; i++)
    if (i != m  &&  i != n) {
      printf sep"%s", $i
      sep=OFS
    }
  print ""
}

These 2 Users Gave Thanks to MadeInGermany For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

9 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Taking nth column and putting its value in n+1 column using awk

Hello Members, Need your expert opinion how to tackle below. I have an input file that looks like below: USS|AWCC|AFGAW|93|70 USSAA|Roshan TDCA|AFGTD|93|72,79 ALB|Vodafone|ALBVF|355|69 ALGEE|Wataniya (Nedjma)|DZAWT|213|50,550 I like output file in below format: ... (7 Replies)
Discussion started by: umarsatti
7 Replies

2. Shell Programming and Scripting

How to search and replace string from nth column from a file?

I wanted to search for a string and replace it with other string from nth column of a file which is comma seperated which I am able to do with below # For Comma seperated file without quotes awk 'BEGIN{OFS=FS=","}$"'"$ColumnNo"'"=="'"$PPK"'"{$"'"$ColumnNo"'"="'"$NPK"'"}{print}' ${FileName} ... (5 Replies)
Discussion started by: Amit Joshi
5 Replies

3. Shell Programming and Scripting

Remove the values from a certain column without deleting the Column name in a .CSV file

(14 Replies)
Discussion started by: dhruuv369
14 Replies

4. Shell Programming and Scripting

Break Column nth in a CSV file into two

Hi Guys, Need help with logic to break Column nth in a CSV file into two for e.g Refer below the second column as the nth column "abcd","","type/beta-version" need output in a following format "abcd","/place/asia/india/mumbai","/product/sw/tomcat","type/beta-version" ... (5 Replies)
Discussion started by: awk-admirer
5 Replies

5. Shell Programming and Scripting

Need help with awk statement to break nth column in csv file into 3 separate columns

Hello Members, I have a csv file in the format below. Need help with awk statement to break nth column into 3 separate columns and export the changes to new file. input file --> file.csv cat file.csv|less "product/fruit/mango","location/asia/india","type/alphonso" need output in... (2 Replies)
Discussion started by: awk-admirer
2 Replies

6. Shell Programming and Scripting

Get the nth word of mth line in a file

Hi.. May be a simple question but I just began to write unix scripts a week ago, for sorting some huge amount of experiment data, so I got no common sense about unix scripting and really need your helps... The situation is, I want to read the nth word of mth line in a file, and then store it... (3 Replies)
Discussion started by: freezelty
3 Replies

7. Shell Programming and Scripting

Calculating average for every Nth line in the Nth column

Is there an awk script that can easily perform the following operation? I have a data file that is in the format of 1944-12,5.6 1945-01,9.8 1945-02,6.7 1945-03,9.3 1945-04,5.9 1945-05,0.7 1945-06,0.0 1945-07,0.0 1945-08,0.0 1945-09,0.0 1945-10,0.2 1945-11,10.5 1945-12,22.3... (3 Replies)
Discussion started by: ncwxpanther
3 Replies

8. Shell Programming and Scripting

Using AWK to find top Nth values in Nth column

I have an awk script to find the maximum value of the 2nd column of a 2 column datafile, but I need to find the top 5 maximum values of the 2nd column. Here is the script that works for the maximum value. awk 'BEGIN { subjectmax=$1 ; max=0} $2 >= max {subjectmax=$1 ; max=$2} END {print... (3 Replies)
Discussion started by: ncwxpanther
3 Replies

9. Shell Programming and Scripting

How to Print from nth field to mth fields using awk

Hi, Is there any short method to print from a particular field till another filed using awk? Example File: File1 ==== 1|2|acv|vbc|......|100|342 2|3|afg|nhj|.......|100|346 Expected output: File2 ==== acv|vbc|.....|100 afg|nhj|.....|100 (8 Replies)
Discussion started by: machomaddy
8 Replies
Login or Register to Ask a Question