Reputation: 1271
Is there a way (in a one-liner) to confine find and replace to within a specific column of a tab-delimited .txt file?
For example:
perl -pe 's/A/B/g;'
But which only finds and replaces 'A' with 'B' within column-2 and ignores all other instances of A, converting this:
1 A A2
2 A A
3 B B1
4 A B
5 A A
6 B A3
7 A A
8 C A
9 E B
10 D B
11 A C6
12 A G
13 B L
14 A E
15 B A
16 A A
Into:
1 B A2
2 B A
3 B B1
4 B B
5 B A
6 B A3
7 B A
8 C A
9 E B
10 D B
11 B C6
12 B G
13 B L
14 B E
15 B A
16 B A
Upvotes: 0
Views: 1182
Reputation: 52162
$ sed 'h;s/^.*\t\(.*\)\t.*$/\1/;y/A/B/;G;s/\(.*\)\n\(.*\t\).*\(\t.*\)/\2\1\3/' infile
1 B A2
2 B A
3 B B1
4 B B
5 B A
6 B A3
7 B A
8 C A
9 E B
10 D B
11 B C6
12 B G
13 B L
14 B E
15 B A
16 B A
Explained:
# Copy pattern space to hold space
h
# Remove first and third column from pattern space
s/^.*\t\(.*\)\t.*$/\1/
# Transliterate A to B (can use s/// for more complex substitutions)
y/A/B/
# Append hold space to pattern space
G
# Replace second column with transliterated value
s/\(.*\)\n\(.*\t\).*\(\t.*\)/\2\1\3/
$ paste <(cut -f 1 infile) <(cut -f 2 infile | tr A B) <(cut -f 3 infile)
This uses paste
, cut
and tr
with process substitution. The tr
can of course be replaced by a sed substitution for more complex changes.
Upvotes: 1
Reputation: 89567
You can write this:
perl -lane '$F[1]=~tr/A/B/;print join("\t", @F)' file
Upvotes: 2
Reputation: 53488
Something like this will transform the second field of a tab separated row.
perl -lne '@row = split /\t/; $row[1] =~ s/A/B/; print join ( "\t", @row );'
Upvotes: 2