Find the answer to your Linux question:
Results 1 to 4 of 4
Just as i thought that i was getting to grips with the vagueries of the Shell, along comes this problem with Sed. According to my current understanding of SED all ...
  1. #1
    Just Joined!
    Join Date
    Mar 2010
    Posts
    16

    I feel slashed to bits

    Just as i thought that i was getting to grips with the vagueries of the Shell, along comes this problem with Sed.
    According to my current understanding of SED all of the below should 'work'.

    But as you see, SED often appears inconsistent for a given pattern;
    and also some of the pattern types seem wrong when they do work.

    Where i have written "should be" or OK, i mean "according to my logic(!)".

    In particular, the info that i have been reading always uses the format "s/abc/def/g" (and also never the ' ) but i have not yet found such a way as that to do what i want; is there one even?

    Can any one explain please?

    Code:
    #!/bin/bash
    
    p='a/b/c/d'
    
    t=`echo "$p" | sed  "s/\//\//g" `
    echo 1 "$t"	# gives a/b/c/d    	ok
    echo 1a "$p" | sed  "s/\//\//g"
    		# gives a/b/c/d    	ok
    t=`echo "$p" | sed  's/\//\//g' `
    echo 1b "$t"	# gives a/b/c/d    	ok
    echo 1c "$p" | sed  's/\//\//g'
    		# gives a/b/c/d    	ok
    echo
    t=`echo "$p" | sed  "s/\//\\\//g" `     # in Kate the \\\ shows as 2 blacks the 3rd in red
    echo 2 "$t"	# gives a/b/c/d		should be a\/b\/c\/d
    echo 2a "$p" | sed  "s/\//\\\//g"       # in Kate the "s/\//\\\//g" is coloured as above
    		# sed: -e expression #1, char 9: unknown option to `s'
    t=`echo "$p" | sed  's/\//\\\//g' `     # in Kate the 's/\//\\\//g' is all in red
    echo 2b "$t"	# sed: -e expression #1, char 9: unknown option to `s'
    		# gives 2b
    echo 2c "$p" | sed  's/\//\\\//g'       # in Kate the 's/\//\\\//g' is coloured as above
    		# gives a\/b\/c\/d	ok
    echo
    t=`echo "$p" | sed  "s/\//\\&/g" `
    echo 3 "$t"	# gives a&b&c&d		should be a\/b\/c\/d
    echo 3a "$p" | sed  "s/\//\\&/g"
    		# gives a&b&c&d		should be a\/b\/c\/d
    t=`echo "$p" | sed  's/\//\\&/g' `
    echo 3b "$t"	# gives a&b&c&d		should be a\/b\/c\/d
    echo 3c "$p" | sed  's/\//\\&/g'
    		# gives a\/b\/c\/d	ok
    echo
    t=`echo "$p" | sed  "s/\//\\\&/g" `     # in Kate \\\ shows as two blacks then red
    echo 4 "$t"	# gives a&b&c&d		should be a\&b\&c\&d
    echo 4a "$p" | sed  "s/\//\\\&/g"       # in Kate \\\ shows as two blacks then red
    		# gives a\/b\/c\/d	should be a\&b\&c\&d
    t=`echo "$p" | sed  's/\//\\\&/g' `     # in Kate \\\ shows as three reds
    echo 4b "$t"	# gives a\/b\/c\/d	should be a\&b\&c\&d
    echo 4c "$p" | sed  's/\//\\\&/g'       # in Kate \\\ shows as three reds
    		# gives a\&b\&c\&d	ok
    echo
    t=`echo "$p" | sed  "s*d*e&*g" `
    echo 5 "$t"	# gives a/b/c/ed	ok
    echo 5a "$p" | sed  "s*d*e&*g"
    		# gives a/b/c/ed	ok
    t=`echo "$p" | sed  's*d*e&*g' `
    echo 5b "$t"	# gives a/b/c/ed	ok
    echo 5c "$p" | sed  's*d*e&*g'
    		# gives a/b/c/ed	ok
    echo
    t=`echo "$p" | sed  "s*\/*\\&*g" `
    echo 6 "$t"	# gives a&b&c&d		should be a\/b\/c\/d
    echo 6a "$p" | sed  "s*\/*\\&*g"
    		# gives a&b&c&d		should be a\/b\/c\/d
    t=`echo "$p" | sed  's*\/*\\&*g' `
    echo 6b "$t"	# gives a&b&c&d		should be a\/b\/c\/d
    echo 6c "$p" | sed  's*\/*\\&*g'
    		# gives a\/b\/c\/d	ok
    echo
    t=`echo "$p" | sed  "s*\/*\\\&*g" `
    echo 7 "$t"	# gives a&b&c&d		should be a\&b\&c\&d
    echo 7a "$p" | sed  "s*\/*\\\&*g"
    		# gives a\/b\/c\/d	should be a\&b\&c\&d
    t=`echo "$p" | sed  's*\/*\\\&*g' `
    echo 7b "$t"	# gives a\/b\/c\/d	should be a\&b\&c\&d
    echo 7c "$p" | sed  's*\/*\\\&*g'
    		# gives a\&b\&c\&d	ok
    echo
    t=`echo "$p" | sed  "s/\//\\&/g" `
    echo 8 "$t"	# gives a&b&c&d		should be a\/b\/c\/d
    echo 8a "$p" | sed  "s/\//\\&/g"
    		# gives a&b&c&d		should be a\/b\/c\/d
    t=`echo "$p" | sed  's/\//\\&/g' `
    echo 8b "$t"	# gives a&b&c&d		should be a\/b\/c\/d
    echo 8c "$p" | sed  's/\//\\&/g'
    		# gives a\/b\/c\/d	ok
    echo
    t=`echo "$p" | sed  "s/\//\\\&/g" `     # in Kate the \\\ shows as 2 blacks the 3rd in red
    echo 9 "$t"	# gives a&b&c&d		should be a\&b\&c\&d
    echo 9a "$p" | sed  "s/\//\\\&/g"       # in Kate the "s/\//\\\&/g" coloured as above
    		# gives a\/b\/c\/d	should be a\&b\&c\&d
    t=`echo "$p" | sed  's/\//\\\&/g' `     # in Kate 's/\//\\\&/g' coloured all in red
    echo 9b "$t"	# gives a\/b\/c\/d	should be a\&b\&c\&d
    echo 9c "$p" | sed  's/\//\\\&/g'       # in Kate 's/\//\\\&/g' coloured as above
    		# gives a\&b\&c\&d	ok
    echo
    t=`echo "$p" | sed  "s*\/*\\\&*g" `     # in Kate the \\\ shows as 2 blacks the 3rd in red
    echo 10 "$t"	# gives a&b&c&d	        should be a\&b\&c\&d
    echo 10a "$p" | sed  "s*\/*\\\&*g"      # in Kate the "s*\/*\\\&*g" is coloured as above
    		# gives a\/b\/c\/d	should be a\&b\&c\&d
    t=`echo "$p" | sed  's*\/*\\\&*g' `     # in Kate the \\\ shows as three reds
    echo 10b "$t"	# gives a\/b\/c\/d	should be a\&b\&c\&d
    echo 10c "$p" | sed  's*\/*\\\&*g'      # in Kate the 's*\/*\\\&*g' is coloured as above
    		# gives a\&b\&c\&d	ok
    echo
    t=`echo "$p" | sed  "s*\/*\\&*g" `      # in Kate the \\ shows in black, the rest in red 
    echo 11 "$t"    # gives a&b&c&d		should be a\/b\/c\/d
    echo 11a "$p" | sed  "s*\/*\\&*g"       # in Kate the "s*\/*\\&*g" coloured as above
                    # gives a&b&c&d	        should be a\/b\/c\/d
    t=`echo "$p" | sed  's*\/*\\&*g' `      # in Kate 's*\/*\\&*g' coloured all in red
    echo 11b "$t"   # gives a&b&c&d	        should be a\/b\/c\/d
    echo 11c "$p" | sed  's*\/*\\&*g'       # in Kate 's*\/*\\&*g' coloured as above
                    # gives a\/b\/c\/d      ok
    echo
    t=`echo "$p" | sed  "s*\/*\&*g" `
    echo 12 "$t"    # gives a&b&c&d		ok
    echo 12a "$p" | sed  "s*\/*\&*g"
                    # gives a&b&c&d		ok
    t=`echo "$p" | sed  's*\/*\&*g' `
    echo 12b "$t"   # gives a&b&c&d		ok
    echo 12c "$p" | sed  's*\/*\&*g'
                    # gives a&b&c&d         ok
    echo
    
    p="/media/hdb8/notes/txts out-notes"
    
    t=`echo "$p" | sed  "s,\/[^\/]*notes\?[ ]*\.*[^\/]*$,-&-,g" `
    echo 13 "$t"    # gives /media/hdb8/notes-/txts out-notes-         ok
    echo 13a "$p" | sed  "s,\/[^\/]*notes\?[ ]*\.*[^\/]*$,-&-,g"
                    # gives /media/hdb8/notes-/txts out-notes-         ok
    t=`echo "$p" | sed  's,\/[^\/]*notes\?[ ]*\.*[^\/]*$,-&-,g' `
    echo 13b "$t"   # gives /media/hdb8/notes-/txts out-notes-         ok
    echo 13c "$p" | sed  's,\/[^\/]*notes\?[ ]*\.*[^\/]*$,-&-,g'
                    # gives /media/hdb8/notes-/txts out-notes-         ok
    echo
    
    #             now trying some deleting
    
    t=`echo "$p" | sed  "\,\/[^\/]*notes\?[ ]*\.*[^\/]*$,d" `
    echo 14 "$t"    # gives  14 then blank   ok
    echo 14a "$p" | sed  "\,\/[^\/]*notes\?[ ]*\.*[^\/]*$,d"
                    # is blank & no newline. ok
    t=`echo "$p" | sed  '\,\/[^\/]*notes\?[ ]*\.*[^\/]*$,d' `
    echo 14b "$t"   # gives  14b then blank  ok
    echo 14c "$p" | sed  '\,\/[^\/]*notes\?[ ]*\.*[^\/]*$,d'
                    # is blank & no newline. ok
    echo
    
    echo  $p | sed "s_notes_-&-_g"
                    # gives /media/hdb8/-notes-/txts out--notes-
    echo
    t=`echo "$p" |  sed  "s_\/[^\/]*notes\?[ ]*\.*[^\/]*$_-&-_g" `
    echo 15 "$t"    # gives sed: -e expression #1, char 35: unterminated `s' command
    echo 15a "$p" | sed  "s_\/[^\/]*notes\?[ ]*\.*[^\/]*$_-&-_g"
                    # gives sed: -e expression #1, char 35: unterminated `s' command
    t=`echo "$p" |  sed  's_\/[^\/]*notes\?[ ]*\.*[^\/]*$_-&-_g' `
    echo 15b "$t"   # gives /media/hdb8/notes-/txts out-notes-         ok
    echo 15c "$p" | sed  's_\/[^\/]*notes\?[ ]*\.*[^\/]*$_-&-_g'
                    # gives /media/hdb8/notes-/txts out-notes-         ok
    
    #    some more deleting
    
    echo v
    t=`echo "$p" |  sed  "\_\/[^\/]*notes\?[ ]*\.*[^\/]*$_d" `
    echo 16 "$t"    # gives sed: -e expression #1, char 30: unterminated address regex      16
    echo w
    echo 16a "$p" | sed  "\_\/[^\/]*notes\?[ ]*\.*[^\/]*$_d"
                    # gives sed: -e expression #1, char 30: unterminated address regex
    echo x
    t=`echo "$p" |  sed  '\_\/[^\/]*notes\?[ ]*\.*[^\/]*$_d' `
    echo 16b "$t"   # is 16b then blank             ok
    echo y
    echo 16c "$p" | sed  '\_\/[^\/]*notes\?[ ]*\.*[^\/]*$_d'
                    # is blank.    ok
    echo z
    p="notes"
    echo
    t=`echo "$p" | sed  "/notes$/d" `
    echo 17 "$t"    # gives  17 then blank
    echo 17a "$p" | sed  "\_notes_d"
                    # is blank & no newline ok
    echo 17b "$p" | sed  "\_notes$_d"
                    # sed: -e expression #1, char 7: unterminated address regex
    t=`echo "$p" | sed  '\_notes$_d' `
    echo 17c "$t"   # gives  17b then blank
    echo 17d "$p" | sed  '\_notes$*_d'
                    # is blank & no newline ok
    echo

  2. #2
    Linux User
    Join Date
    Nov 2009
    Location
    France
    Posts
    292
    I haven't gone through all the list which is too long but at least, if you want the escape char to appear in the output, you escape it twice. Can't really explain precisely why, it may seem that the first escape is interpreted by bash (\\\\) and the resulting \\ would be what gets to sed. This is not really an explanation, I hope some sed gurus shed some light here.

    Code:
    echo "$p" | sed  "s/\//\\\//g
    echo "$p" | sed  "s/\//\\\\\//g
    0 + 1 = 1 != 2 <> 3 != 4 ...
    Until the camel can pass though the eye of the needle.

  3. #3
    Just Joined!
    Join Date
    Jul 2006
    Location
    localhost
    Posts
    22
    I can't really say I'm a sed guru, but there are some things to note here:


    1. 's/\//\\\//g' is not the same as "s/\//\\\//g":
    echo "s/\//\\\//g" # returns s/\//\\//g
    echo 's/\//\\\//g' # returns s/\//\\\//g

    This is better illustrated like this:
    s=hello
    echo ''$s" # returns hello
    echo '$s' # returns $s

    This is due to how bash interprets the quoted string, and as nmset pointed out bash looks through quoted strings and tries to expand them for the program it is passed to.
    This is why you can use variables in a quoted string.

    However, when a string is enclosed within single quotes ('), bash will pass the raw string without interpreting it at all.
    This is very useful for programs like sed where you may want to use special characters but don't want bash to help you.

    In short, don't mix both kinds in a script as you'll most likely end up confused.


    2. You should consider using a different delimiter than "/" when it is used elsewhere in the expression for better readability:

    sed 's+\/+\\\/+g'
    # is equal to
    sed 's/\//\\\//g'

    sed 's§\/§\\\/§g'
    # is also equal to
    sed 's/\//\\\//g'

    You may use any character (even * or . may be used, but it's not recommended) as a delimiter, however the delimiter can not be a part of the search or replace string.
    The delimiter is the character immediatedly after the sed command (in most cases the "s" at the beginning of the expression); if the expression starts with "s+" then "+" is the delimiter.

    This is also less confusing.


    3. There are many complex ways to use sed and don't feel ashamed of yourself if you need a beginners guide to figure things out.

    There are quite a few resources in sed, but the ones I end up using the most would be the manpage and (it turns out I'm not allowed to post URLs yet, but a Google search on "Getting started with sed" should get you there).


    I hope this will hep you figure it out.

    / Djhg2000

  4. #4
    Just Joined!
    Join Date
    Mar 2010
    Posts
    16
    Thanks for the tips & references.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...