jasminewu229
jasminewu229

Reputation: 11

replace some spaces with underscores in linux

I have a file that looks like this:

some text some text some text.
some other text. and others.
text text text ![Screenshot 2020-05-29 at 4.14.08 pm](./images/Screenshot 2020-05-29 at 4.14.08 pm.png)
![Screenshot 2020-05-29 at 4.04.08 pm](./images/Screenshot 2020-05-29 at 4.04.08 pm.png)
Some other text.
![Screenshot 2020-05-29 at 4.04.09 pm](./images/Screenshot 2020-05-29 at 4.04.09 pm.png) text text text
text text text ![Screenshot 2020-06-29 at 4.04.09 pm](./images/Screenshot 2020-06-29 at 4.04.09 pm.png) text text text

I want to replace the space with underscore in Screenshot names so that it becomes:

some text some text some text.
some other text. and others.
text text text ![Screenshot_2020-05-29_at_4.14.08_pm](./images/Screenshot_2020-05-29_at_4.14.08_pm.png)
![Screenshot_2020-05-29_at_4.04.08_pm](./images/Screenshot_2020-05-29_at_4.04.08_pm.png)
some other text.
![Screenshot_2020-05-29_at_4.04.09_pm](./images/Screenshot_2020-05-29_at_4.04.09_pm.png) text text text
text text text ![Screenshot_2020-06-29_at_4.04.09_pm](./images/Screenshot_2020-06-29_at_4.04.09_pm.png) text text text

Can sed do this?

If I use sed -e "s/ /_/g", then all spaces, not just those in Screenshot file names, would be changed. I don't want to replace spaces in other text.

Thanks to anyone that could help out!

Upvotes: 0

Views: 334

Answers (3)

Walter A
Walter A

Reputation: 20002

When the screenshot string continues until the first ) or ], first put each screenshot string on a seperate line:

tr "\n" "\r" < "${file}" | sed -r 's/Screenshot|\]|\)/\n&/g' | 
   sed -r '/Screenshot/ s/ /_/g'  | tr -d '\n' | tr '\r' '\n'

Upvotes: 0

anubhava
anubhava

Reputation: 785126

Looking at your sample data and your comment you may use this perl:

perl -pe 's/(?:\[Screenshot|(?!^)\G[^] ]+)\K (?=[^]]*])|(?:\([^) ]*Screenshot|(?!^)\G[^) ]+)\K (?=[^)]*\))/_/g' file
some text some text some text.
some other text. and others.
text text text ![Screenshot_2020-05-29_at_4.14.08_pm](./images/Screenshot_2020-05-29_at_4.14.08_pm.png)
![Screenshot_2020-05-29_at_4.04.08_pm](./images/Screenshot_2020-05-29_at_4.04.08_pm.png)
Some other text.
![Screenshot_2020-05-29_at_4.04.09_pm](./images/Screenshot_2020-05-29_at_4.04.09_pm.png) text text text
text text text ![Screenshot_2020-06-29_at_4.04.09_pm](./images/Screenshot_2020-06-29_at_4.04.09_pm.png) text text text

RegEx Demo

RegEx Details:

  • (?:: Start non-capture group

    • !\[Screenshot: Match text ![ScreenShot
    • |: OR
    • (?!^)\G: \G asserts position at the end of the previous match or line start. (?!^) ensures \G doesn't match at line start.
    • [^] ]+: Match 1 or more of any character that is not space or ]
  • ): End non-capture group

  • \K: Reset Match Info

  • (?=[^]]*]): Lookahead to ensure we have a ] ahead of us

  • |(?:\([^) ]*Screenshot|(?!^)\G[^) ]+)\K (?=[^)]*\)): Do same for (.*Screenshot.*.) string

Upvotes: 1

potong
potong

Reputation: 58400

This might work for you (GNU sed):

sed '/^!\[Screenshot /y/ /_/' file

The y command is seds translate command similiar to the tr command line command.

If there is text before the text you want spaces underlined to remain with spaces in it, use this:

sed '/^!\[Screenshot /{s//\n&;h;y/_/ /;H;g;s/\n.*\n//}' file

This cuts the line in two, copies, amends and joins back the two parts, with the back half amended.

Upvotes: 0

Related Questions