Search code examples
unixawkcut

cut command --complement flag equivalent in AWK for a complex parameter


this question is a followup on to existing question

don't mark this as duplicate as the expectation of the question is totally different

I am trying to write an AWK command which does exactly the below

Command 1:

cut --complement -c $IGNORE_RANGE file.txt > tmp

Command 2:

cut --complement -d, -f$IGNORE_RANGE $report  > tmp

$IGNORE_RANGE can be of any value say, 1-5,6 or 1,3,5 1,3-5 etc

i cannot use cut since i am in AIX and AIX does not support --complement, is there any way to achieve this using AWK command

Example for Command 1:

file.txt

abcdefg
1234567

Output

cut --complement -c 1-5,6 file.txt > tmp
g
7


cut --complement -c 1,3,5 file.txt > tmp
bdfg
2467

cut --complement -c 1,3-5 file.txt > tmp
bfg
267

Example for Command 2:

file.txt

data1,data2,data3,data4,data5,data6,data7

Output

cut --complement -d, -f 1-5,6 file.txt > tmp
data7

cut --complement -d, -f 1,3,5 file.txt > tmp
data2,data4,data6,data7

cut --complement -d, -f 1,3-5 file.txt > tmp
data2,data6,data7

Solution

  • 1st solution for OP's position number problem: Could you please try following, a generic solution based on provided samples written and tested in GNU awk and needed GNU awk to be executed. One could give ranges or individual position number separated by , in awk's ignore_pos variable.

    awk -v FS= -v ignore_pos="1-5,6" '
    BEGIN{
      num=split(ignore_pos,array1,",")
      for(i=1;i<=num;i++){
        if(array1[i]~/-/){
           split(array1[i],array2,"-")
           for(j=array2[1];j<=array2[2];j++){
             ignore[j]
           }
        }
        else{
           ignore[array1[i]]
        }
      }
    }
    {
      for(i=1;i<=NF;i++){
        if(!(i in ignore)){ val=val $i }
      }
      $0=val
      val=""
    }
    1
    '  Input_file
    


    2nd solution for OP's field number problem: When one wants to ignore fields we could use this solution then(OP's command2 examples taken here to run this). As per OP's samples ,comma has been made as field separator for Input_file here.

    awk -v ignore_field="1-5,6" '
    BEGIN{
      FS=OFS=","
      num=split(ignore_pos,array1,",")
      for(i=1;i<=num;i++){
        if(array1[i]~/-/){
          split(array1[i],array2,"-")
          for(j=array2[1];j<=array2[2];j++){
            ignoreFields[j]
          }
        }
        else{
          ignoreFields[array1[i]]
        }
      }
    }
    {
      for(i=1;i<=NF;i++){
        val=""
        if(!(i in ignoreFields)){  val=(val?val OFS:"")$i  }
      }
      $0=val
    }
    1
    ' Input_file