3

I have already seen other answers trying to solve my problem but I am not able to solve it.

#!/bin/bash
s=org.gnome.Terminal.Legacy.Keybindings
g=$(echo $s | sed "s|\.|/|g") 
echo $g

I have above script which returns

org/gnome/Terminal/Legacy/Keybindings

but I need to append / at the end of this so that it becomes

org/gnome/Terminal/Legacy/Keybindings/

How to extend my sed script for this?

0

5 Answers 5

9

You don't really need sed for this, if you're using bash.

s="org.gnome.Terminal.Legacy.Keybindings"
g=${s//.//}/

Read the Parameter Expansion section of bash man page (${parameter/pattern/string}), it also has many other useful things.

With sed, you can also specify multiple expressions, sometimes it is more readable.

s="org.gnome.Terminal.Legacy.Keybindings"
g=$(sed -e 'y,.,/,' -e 's,$,/,' <<<$s)

Note that with y command you don't have to escape the ., y command accepts literal characters.

6

Try this:

sed 's/\.\|$/\//g'
  • | is the alternation operator.
  • $ will match the end of line.

Demo:

%echo org.gnome.Terminal.Legacy.Keybindings|sed 's/\.\|$/\//g'
org/gnome/Terminal/Legacy/Keybindings/
4

sed approach:

s="org.gnome.Terminal.Legacy.Keybindings"
g=$(echo $s | sed "y|.|/|; s|$|/|")
echo $g
org/gnome/Terminal/Legacy/Keybindings/

  • y|\.|/| - translate all dots . to slashes /
5
  • what is the difference between s|ToBeReplaced|ReplaceByThis and y|ToBeReplaced|ReplaceByThis in sed Jul 3, 2017 at 21:22
  • 2
    @GypsyCosmonaut, 1) y/src/dst/ - Transliterate any characters in the pattern space which match any of the source-chars with the corresponding character in dest-chars. 2) s/regexp/replacement/flags - the s command attempts to match the pattern space against the supplied regular expression regexp; if the match is successful, then that portion of the pattern space which was matched is replaced with replacement. Jul 3, 2017 at 21:25
  • thank you Roman, do you have any suggestions for any books where I can learn sed from? Jul 3, 2017 at 21:30
  • 3
    You don't need to escape . for the y command, it accepts literal characters. y|.|/|. The y commands transliterates, matching single characters from src and replacing them with characters from dst. E.g. y,abcdefghijklmnoprstuvwxyz,ABCDEFGHIJKLMNOPRSTUVWXYZ, would change all text to upper-case. Jul 3, 2017 at 21:31
  • @GenePavlovsky, that was easy Jul 4, 2017 at 6:08
1

You could do

#!/bin/bash
s=org.gnome.Terminal.Legacy.Keybindings
g=$(echo $s | sed "s|\.|/|g") 
echo $(echo "$g" | sed 's@$@/@')

it searches for The end of the line ($) and replaces it with a /.

@ is an alternative seperator.

2
  • @ is not that readable in my opinion, I prefer ,. Jul 3, 2017 at 21:30
  • I prefer @ because it's the only symbol that I never needed in a script except as seperator. @GenePavlovsky
    – ADDB
    Jul 3, 2017 at 21:31
1

You're doing two things with sed here:

  1. replacing all the dots with slashes, and
  2. adding a slash to the end of line

The first task may be done by the sed command y#.#/#. The y command is similar to how the tr utility works in that it replaces characters from one string to another without involving regular expressions. The three # are delimiters for the command (it usually uses /, as in y/A-Z/a-z/ to lowercase all characters in the A-Z range), but just like with the s command, we may use any delimiter we want.

The second task may be done by replacing the end of line with a slash using s#$#/#.

Putting these together, we get

sed -e 'y#.#/#' -e 's#$#/#'

In your script:

#!/bin/bash
s='org.gnome.Terminal.Legacy.Keybindings'
g=$( sed -e 'y#.#/#' -e 's#$#/#' <<<"$s" )
printf '%s\n' "$g"

This produces

org/gnome/Terminal/Legacy/Keybindings/

Of course, the slash may be put in by the printf and the replacements of the dots with slashes may be done with tr too:

#!/bin/bash
s='org.gnome.Terminal.Legacy.Keybindings'
g=$( tr '.' '/' <<<"$s" )
printf '%s/\n' "$g"
3
  • What is the difference between sed 's/text1/text2', sed 's:text1:text2', sed 's@text1@text2', sed 's#text1#text2', sed 's|text1|text2'? Can we use any special symbol we want or do these /:@#| have some meaning? Jul 4, 2017 at 8:54
  • 1
    @GypsyCosmonaut All of those contains syntax errors; the last delimiter (/, :, @ and # respectively) is missing. Apart from that, all are equivalent. You may choose whichever character you want to delimit the s command: sshellosworlds will replace hello with world, as would s/hello/world/ and s!hello!world!. It's allowed to get rid of the "leaning toothpick syndrome": s/\/var\/log\//\/usr\/var\/log\// --> s#/var/log/#/usr/var/log/#.
    – Kusalananda
    Jul 4, 2017 at 8:57
  • 1
    @GypsyCosmonaut Just for fun: I looked through the dictionary for words that were sed substitution commands. sentence would replace nt with nc, for example.
    – Kusalananda
    Jul 4, 2017 at 9:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .