3

I have data in notepad like this:

4480-1
4480-2
4480-3
4480-15
4581-1
4581-2
4581-3
4581-4

Can we do it using for loop sort of things? With sed?

My required output is 4480-1&-2&-3&-15&4581-1&-2&-3&-4

1

This should work:

awk -F- '$1!=a{printf "%s", $1} {printf "-%s&", $2} {a=$1}' file | sed 's/&$/\n/g'

Outout:

4480-1&-2&-3&-15&4581-1&-2&-3&-4

Explanantion:

  • awk -F- delimiter is -
  • $1!=a{printf "%s", $1} print the first part 4480 if it's not the same as in the last processed line
  • {printf "-%s&", $2} print the second part with & at the end
  • {a=$1} set a to the processed line
  • sed 's/&$/\n/g' remove the last character that is a & and add a newline
1

I dont' think you can do it with sed easily. It's easier with perl:

$ perl -F'-' -anle '
    $h{$F[0]} .= defined($h{$F[0]}) ? "&-".$F[1] : "-".$F[1];
    END {
        $,="&";
        print @{[map { $_.$h{$_} } sort { $a <=> $b } keys %h]}
    }
' file
4480-1&-2&-3&-15&4581-1&-2&-3&-4
  • The output is slightly different than the one in the question, when the next starting number is encountered, there shouldn't be an & at first. – Chris Down Jun 25 '14 at 12:17
  • @ChrisDown: Try again, I still editting my answer when you see it. – cuonglm Jun 25 '14 at 12:19
0

Probably not possible with sed. I'm doing with AWK. I assume one entry per line.

awk '
  BEGIN { FS="-"; ORS=""; left="" }

  {
    if(NR>1){print "&"}

    # Only print left part if it differs from previous line
    if ($1!=left) {
      print $1 "-" $2
      left=$1;
    } else {
      print "-" $2
    }
  }' inputfile.txt

Outputs 4480-1&-2&-3&-15&4581-1&-2&-3&-4

0

If your input isn't really sorted as in the question, you should use sort -n file, first.

awk '
{
    split($1, id, "-")

    if (NR > 1) {
        printf "&"
    }

    if (prefix_test[id[1]]++ == 0) {
        printf("%s", id[1])
    }

    printf("-%s", id[2])
}

END { printf "\n" }' file
0

Should be sed, however here is perl:

#!/usr/bin/perl

while ( ($a,$b) = split /-/,<>) { $n->{$a}->{"-$b"}++;}

@_ = map { $_,
           map { chomp; "$_&"; } reverse sort { $a <=> $b } keys $n->{$_};
     } sort { $a <=> $b } keys $n;

@_[-1] =~ s/&$//;

print @_;

numerically sorted output, not depending the input order:

4480-1&-2&-3&-15&4581-1&-2&-3&-4
  • Thanks chaos..it's working. i have one more requirement like, in a note pad above data comes between 2 lines like "VMG100" & "VMG102",this thing keeps on going... i want format as VMG100 & above output....VMG101 followed by (output to some other data) – user73553 Jun 25 '14 at 12:35
  • Yu're welcome. It would be nice when you post a new question belonging to your needs. – user55518 Jun 25 '14 at 18:35
0

An awk solution that doesn't require the entries to be sorted by prefix

awk -F- '
    {a[$1] = !a[$1]? $1"-"$2 : a[$1]"&-"$2} 
END {asort(a); for (i in a) printf "%s&", a[i]}
' file | sed 's/&$/\n/'

If you don't need the output to be sorted, you can omit the asort(a)

awk -F- '
    {a[$1] = !a[$1]? $1"-"$2 : a[$1]"&-"$2} 
END {for (i in a) printf "%s&", a[i]}
' file | sed 's/&$/\n/'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.