'Move field matching pattern to first field

I have a file of hundreds of lines e.g:

CAT FROG DOG PIG

DOG PIG BIRD HORSE

HORSE FROG PIG

And I wand to move any field containing "PIG" to the first field as below:

PIG CAT FROG DOG

PIG DOG BIRD HORSE

PIG HORSE FROG

Is it possible to do in an awk one liner? I was trying to reverse engineer this line I found in another thread that moves fields matching a pattern to the end but my knowledge of awk is not great:

awk '{ for(i=1; i<=NF; i++) if($i~/PIG/) a[i]++; } {for(i in a){str=str $i FS; $i=""} $0=$0 FS str; $1=$1; str=""}1' file

Many thanks for any help.



Solution 1:[1]

awk '{
    out = $1
    for (i=2; i<=NF; i++) {
        out = ($i ~ /PIG/ ? $i OFS out : out OFS $i)
    }
    print out
}'

Original answer below would produce the posted expected output from the posted sample input but would fail in some of the non-trivial cases not covered by the provided sample input as the assignment to $0 in the loop resplits the record, renumbering the fields and so could skip a field:

awk '{
    for (i=1; i<=NF; i++) {
        if ($i ~ /PIG/) {
            tmp = $i
            $i = ""
            $0 = tmp FS $0
        }
    }
    $1 = $1
    print
}' file

Solution 2:[2]

Here's a one-liner solution:

echo
echo "${test1}"
echo

<<<"${test1}" mawk '(NF*=!_<NF) && \
                          sub("^",FS" ")+\
                      gsub("[ \t]+"," ")' FS='PIG' OFS=''

CAT FROG DOG PIG
DOG PIG BIRD HORSE
HORSE FROG PIG
FROG DOG HORSE

PIG CAT FROG DOG 
PIG DOG BIRD HORSE
PIG HORSE FROG 

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 RARE Kpop Manifesto