Reputation: 97
I am trying to get 20th character of each line, if its b
then exchange last 2 columns with each other values AND if its B
then 3rd last column and last column's value should be exchanged, like shown below.
Sample of input:
1234567891011121314b abcd erfg ijkl 12114353 blabla
1234567891011121314Babcd erfg ijkl 12114353 blabla
Sample of expected output:
1234567891011121314b abcd erfg ijkl blabla 12114353
123456789101112131Babcd erfg blabla 12114353 ijkl
I tried following code:
while read value
do
echo "$value" | cut -c20
done < "file"
I also tried to use awk
's substr
but couldn't proceed too much in it too.
Actual file is same like shown sample above; please guide me.
Upvotes: 2
Views: 97
Reputation: 23677
With perl
perl -lpe 's/^.{19}([bB]).*?\K(\s+\S+)(\s+\S+)(\s+\S+)$/$1 eq "b" ? "$2$4$3" : "$4$3$2"/e'
^.{19}([bB]).*?\K
capture the 20th character (only if it is b
or B
) and ignore all text except last three columnse
flag allows Perl code in replacement section$1 eq "b"
checks if 20th character is b
With sed
(syntax checked with GNU sed
, might differ for other implementations), modifying the answer from @costaparas, assuming 20th character is always b
or B
sed -E '/^.{19}b/ s/([^ ]+) ([^ ]+)\s*$/\2 \1/; t; s/([^ ]+) ([^ ]+) ([^ ]+)\s*$/\3 \2 \1/'
/^.{19}b/
checks if 20th character is b
t
command/^.{19}B/
before the second substitution if neededUpvotes: 1
Reputation: 5237
If you want to do it the long way using your current approach, you can use sed
to finish it off.
Simply check what the 20th character is, and do the appropriate swap in either case using a sed
substitution. The swap is achieved using 2 or 3 capture groups, depending on which case the line satisfies.
file='file.txt'
while read -r value
do
b=$(echo "$value" | cut -c20)
if [ "$b" = 'b' ]
then
echo "$value" | sed -E 's/([^ ]+) ([^ ]+)\s*$/\2 \1/'
elif [ "$b" = 'B' ]
then
echo "$value" | sed -E 's/([^ ]+) ([^ ]+) ([^ ]+)\s*$/\3 \2 \1/'
fi
done < "$file"
This assumes your fields are space-delimited.
In both cases, we anchor the match to the end of the line, and also account for potential trailing whitespace (which we don't bother substituting back in - but you can if you want to).
Output:
1234567891011121314b abcd erfg ijkl blabla 12114353
1234567891011121314Babcd erfg blabla 12114353 ijkl
Upvotes: 1
Reputation: 36640
I would use GNU AWK
for that task following way, let file.txt
content be
12345678910111213141b abcd erfg ijkl 12114353 blabla
12345678910111213141Babcd erfg ijkl 12114353 blabla
then
awk '{lastcol=$NF}/^.{20}b/{$NF=$(NF-1);$(NF-1)=lastcol}/^.{20}B/{$NF=$3;$3=lastcol}{print}' file.txt
output
12345678910111213141b abcd erfg ijkl blabla 12114353
12345678910111213141Babcd erfg blabla 12114353 ijkl
Explanation: for every line store last column content as lastcol
, if line startswith 20 of any characters followed by b
then set content of last row to what is 2nd from end column and content of 2nd from end column to lastcol
, if line startswith 20 of any characters folllowed by B
then set content of last column to what is in 3rd column and content of 3rd column to lastcol
. print
such line.
(tested in gawk 4.2.1)
Upvotes: 2
Reputation: 133650
Based on your shown samples, could you please try following. Written and tested in GNU awk
.
awk '
{
val=substr($0,20,1)
}
val=="b"{
temp=$(NF-1)
$(NF-1)=$NF
$NF=temp
temp=""
}
val=="B"{
temp=$(NF-2)
$(NF-2)=$NF
$NF=temp
temp=""
}
1' Input_file
Explanation: Adding detailed explanation for above.
awk ' ##Starting awk program from here.
{
val=substr($0,20,1) ##getting 20th character value here.
}
val=="b"{ ##Checking condition if val is b then do following.
temp=$(NF-1) ##Creating temp with 2nd last field value here.
$(NF-1)=$NF ##Setting last field value to 2nd last field here.
$NF=temp ##Again setting last field as temp.
temp="" ##Nullifying temp here.
}
val=="B"{ ##Checking condition if val is B then do following.
temp=$(NF-2) ##Creating temp which has 3rd last field value here.
$(NF-2)=$NF ##Setting 3rd last field value to last field here.
$NF=temp ##Again setting last field as temp.
temp="" ##Nullifying temp here.
}
1 ##Printing current line here.
' Input_file ##Mentioning Input_file name here.
Upvotes: 3