2

I want column 2 to have the string Piebald, the order of the other strings doesn't matter. I have:

HR0024  Black pastel    Piebald
HR0028  Piebald
MC0023  Piebald
MC0039  Fire    Piebald
MC0075  Piebald VPI Axanthic
MC0082  Pastel  Piebald
MC0120  Piebald Yellowbelly     Het-Lavender
MC0124  Super-Pastel    Piebald Het-Clown
MC0126  Fire    Pastel  Piebald
MC0144  Piebald Vanilla

I want something like this:

HR0024 Piebald pastel Black
HR0028 Piebald
MC0023 Piebald
MC0039 Piebald Fire
MC0075 Piebald VPI Axanthic
MC0082 Piebald Pastel
MC0120 Piebald Yellowbelly Het-Lavender
MC0124 Piebald Super-Pastel Het-Clown
MC0126 Piebald Pastel Fire
MC0144 Piebald Vanilla

Some rows are going to have the target strings on different columns (2, 3, or 4). I don't think cut -f does the job here, I think awk or sed is needed. Any help is appreciated.

  • What is your field separator, a tab? – Freddy Oct 30 at 21:04
  • yes, it was tab – Age87 Oct 30 at 23:33
5

With awk, we loop over the fields and if we find the chosen one, we swap with the second field.

awk -v p="Piebald" '{
    for (i=2;i<=NF;i++) if ($i == p) {$i = $2; $2 = p; break}
}1' file
  • 1 at the end means print the line.
  • break exits early the loop after swapping
  • -v var="value" is the standard way to pass a variable to awk.
  • Also, this way, any sequential spaces in the input are shrinking to one space, which is the default output field separator.

Output:

HR0024 Piebald pastel Black
HR0028 Piebald
MC0023 Piebald
MC0039 Piebald Fire
MC0075 Piebald VPI Axanthic
MC0082 Piebald Pastel
MC0120 Piebald Yellowbelly Het. lavender
| improve this answer | |
  • Perfect! I changed the input slightly so that a few spaces weren't treated as different fields (e.g. "Het. lavender" is now "Het-Lavender"). – Age87 Oct 30 at 23:21
  • 1
    @Age87 Try it as awk -F'\t' -v OFS='\t' -v p="Piebald" ... to not confuse spaces and tabs. – Freddy Oct 30 at 23:54
3

If the order of the other strings doesn't matter, you can just do:

$ sed -E 's/Piebald//g; s/^(\S+)/\1 Piebald/' file 
HR0024 Piebald  Black pastel    
HR0028 Piebald  
MC0023 Piebald  
MC0039 Piebald  Fire    
MC0075 Piebald   VPI Axanthic
MC0082 Piebald  Pastel  
MC0120 Piebald   Yellowbelly     Het-Lavender
MC0124 Piebald  Super-Pastel     Het-Clown
MC0126 Piebald  Fire    Pastel  
MC0144 Piebald   Vanilla

Or, if your sed doesn't support that:

$ perl -pe 's/Piebald//g; s/^(\S+)/\1 Piebald/' file 
HR0024 Piebald  Black pastel    
HR0028 Piebald  
MC0023 Piebald  
MC0039 Piebald  Fire    
MC0075 Piebald   VPI Axanthic
MC0082 Piebald  Pastel  
MC0120 Piebald   Yellowbelly     Het-Lavender
MC0124 Piebald  Super-Pastel     Het-Clown
MC0126 Piebald  Fire    Pastel  
MC0144 Piebald   Vanilla
| improve this answer | |

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.