4

For example, I got a line like this:

44567743346_567864_56788_5677_3

I want to change all the _ into :, except for the last one would change into \. The expected output is:

44567743346:567864:56788:5677\3

5 Answers5

6
$ echo '44567743346_567864_56788_5677_3' | sed -r 's|_|:|g; s|:([^:]*)$|\\\1|'
44567743346:567864:56788:5677\3

This uses two sed substitution commands. The first, s|_|:|g changes all underlines to colons. The second, s|:([^:]*)$|\\\1| finds the last colon and changes it to a backslash.

Modifying every fourth line of a file this way

sed -r '1~4{s|_|:|g; s|:([^:]*)$|\\\1|;}' file

To modify the file in-place:

sed -i -r '1~4{s|_|:|g; s|:([^:]*)$|\\\1|;}' file
John1024
  • 13,687
  • 43
  • 51
2

If you know the count of the last occurrence of _ e.g. in your example the last _ is the 4th _ in the line, you can do :

sed 's/_/\\/4; s/_/:/g' file.txt

Here we have first converted the 4th (last) occurrence of _ to \, then the remaining occurrences of _ are converted to :.

For example :

$ echo '44567743346_567864_56788_5677_3' | sed 's/_/\\/4; s/_/:/g'
44567743346:567864:56788:5677\3

On the other hand if you don't know the position of the last occurrence of _, you can greedily match upto the last occurrence of _, replace it with \ and then replace the rest with : :

sed -r 's/^(.*)_/\1\\/; s/_/:/g' file.txt

For example :

$ echo '44567743346_567864_56788_5677_3' | sed -r 's/^(.*)_/\1\\/; s/_/:/g'
44567743346:567864:56788:5677\3
heemayl
  • 91,753
2

A Simple One Using sed

echo "44567743346_567864_56788_5677_3" | rev | sed "s/_/:/2g" | sed 's/_/\\/' | rev


Now let's see how it works:-

1) rev reverses the string,

it becomes 3_7765_88765_468765_64334776544

2) sed "s/_/:/2g replaces all occurrence of _ to : except the first occurrence in reversed string,

it becomes, 3_7765:88765:468765:64334776544

3) Next sed i.e. sed 's/_/\\/' replaces just the first occurrence of _ to \.

It becomes, 3\7765:88765:468765:64334776544

4) rev reverses this processed string

Now, final string is:-

44567743346:567864:56788:5677\3

Now, its done!

Note: It doesn't give much efficiency. Its here just because its simple

Devesh Saini
  • 155
  • 5
0

Works in any line length:

$ echo "44567743346_567864_56788_5677_3" | sed -E 's/^(.*)_/\1\\/; s/_/:/g'
44567743346:567864:56788:5677\3
storenth
  • 101
0

Why sed if it's simpler using awk?

awk -F_ '{printf "%s",$1; for(i=2;i<NF;i++){printf ":%s",$i}; printf "\\%s\n",$NF}' your_input_file

And as you said in a comment? you need only every fourth line

awk -F_ '(NR % 4) == 1 {printf "%s",$1; for(i=2;i<NF;i++){printf ":%s",$i}; printf "\\%s\n",$NF; next} {print}'  your_input_file

Example

Input file

% cat foo
1_44567743346_567864_56788_5677_3
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22
1_44567743346_567864_56788_5677_3
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22
1_44567743346_567864_56788_5677_3
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22
1_44567743346_567864_56788_5677_3
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22

Command output to change every fourth line

% awk -F_ '(NR % 4) == 1 {printf "%s",$1; for(i=2;i<NF;i++){printf ":%s",$i}; printf "\\%s\n",$NF; next} {print}' foo
1:44567743346:567864:56788:5677\3
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22
1:44567743346:567864:56788:5677\3
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22
1:44567743346:567864:56788:5677\3
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22
1:44567743346:567864:56788:5677\3
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22

Command output to change each line

% awk -F_ '{printf "%s",$1; for(i=2;i<NF;i++){printf ":%s",$i}; printf "\\%s\n",$NF}' foo                               
1:44567743346:567864:56788:5677\3
2:908798:08098:878:24332:24:24244\22
3:44567743346:567864:56788:5677\3
4:908798:08098:878:24332:24:24244\22
1:44567743346:567864:56788:5677\3
2:908798:08098:878:24332:24:24244\22
3:44567743346:567864:56788:5677\3
4:908798:08098:878:24332:24:24244\22
1:44567743346:567864:56788:5677\3
2:908798:08098:878:24332:24:24244\22
3:44567743346:567864:56788:5677\3
4:908798:08098:878:24332:24:24244\22
1:44567743346:567864:56788:5677\3
2:908798:08098:878:24332:24:24244\22
3:44567743346:567864:56788:5677\3
4:908798:08098:878:24332:24:24244\22
A.B.
  • 90,397