[ACCEPTED]-sed rare-delimiter (other than & | / ?...)-delimiter

Accepted answer
Score: 17

The characters in the input file are of 16 no concern - sed parses them fine. There may 15 be an issue, however, if you have most of 14 the common characters in your pattern - or if your 13 pattern may not be known beforehand.

At least 12 on GNU sed, you can use a non-printable character 11 that is highly improbable to exist in your 10 pattern as a delimiter. For example, if 9 your shell is Bash:

$ echo '|||' | sed s$'\001''|'$'\001''/'$'\001''g'

In this example, Bash replaces $'\001' with 8 the character that has the octal value 001 - in 7 ASCII it's the SOH character (start of heading).

Since 6 such characters are control/non-printable 5 characters, it's doubtful that they will 4 exist in the pattern. Unless, that is, you 3 are doing something weird like modifying 2 binary files - or Unicode files without 1 the proper locale settings.

Score: 2

Another way to do this is to use Shell Parameter 2 Substitution.

${parameter/pattern/replace}  # substitute replace for pattern once

or

${parameter//pattern/replace}  # substitute replace for pattern everywhere

Here is a quite complex example 1 that is difficult with sed:

$ parameter="Common sed delimiters: [sed-del]"
$ pattern="\[sed-del\]"
$ replace="[/_%:\\@]"
$ echo "${parameter//$pattern/replace}"

result is:

Common sed delimiters: [/_%:\@]

However: This only work with bash parameters and not files where sed excel.

Score: 1

There is no such option for multi-character 8 expression delimiters in sed, but I doubt you 7 need that. The delimiter character should 6 not occur in the pattern, but if it appears in 5 the string being processed, it's not a problem. And 4 unless you're doing something extremely 3 weird, there will always be some character 2 that doesn't appear in your search pattern 1 that can serve as a delimiter.

Score: 1

You need the nested delimiter facility that 23 Perl offers. That allows to use stuff like 22 matching, substituting, and transliterating 21 without worrying about the delimiter being 20 included in your contents. Since perl is 19 a superset of sed, you should be able to 18 use it for whatever you’re used sed for.

Consider 17 this:

$ perl -nle 'print if /something/' inputs

Now if your something contains a slash, you 16 have a problem. The way to fix this is to 15 change delimiter, preferably to a bracketing 14 one. So for example, you could having anything 13 you like in the $WHATEVER shell variable 12 (provided the backets are balanced), which 11 gets interpolated by the shell before Perl 10 is even called here:

 $ perl -nle "print if m($WHATEVER)" /usr/share/dict/words

That works even if you 9 have correctly nested parens in $WHATEVER. The 8 four bracketing pairs which correctly nest 7 like this in Perl are < >, ( ), [ ], and { }. They 6 allow arbitrary contents that include the 5 delimiter if that delimiter is balanced.

If 4 it is not balanced, then do not use a delimiter 3 at all. If the pattern is in a Perl variable, you 2 don’t need to use the match operator provided 1 you use the =~ operator, so:

$whatever = "some arbitrary string ( / # [ etc";
if ($line =~ $whatever) { ... }
Score: 1

With the help of Jim Lewis, I finally did 1 a test before using sed :

if [ `echo $1 | grep '|'` ]; then
    grep ".*$1.*:" $DB_FILE  | sed "s@^.*$1*.*\(:\)@@ "
else
    grep ".*$1.*:" $DB_FILE  | sed "s|^.*$1*.*\(:\)|| "
fi

Thanks for help

Score: 1

Escaping the delimiter inline for BASH to 7 parse is cumbersome and difficult to read 6 (although the delimiter does need escaping 5 for sed's benefit when it's first used, per-expression).

To 4 pull together thkala's answer and user4401178's comment:

DELIM=$(echo -en "\001");
sed -n "\\${DELIM}${STARTING_SEARCH_TERM}${DELIM},\\${DELIM}${ENDING_SEARCH_TERM}${DELIM}p" "${FILE}"

This 3 example returns all results starting from 2 ${STARTING_SEARCH_TERM} until ${ENDING_SEARCH_TERM} that don't match the SOH (start of 1 heading) character with ASCII code 001.

Score: 1

There's no universal separator, but it can 11 be escaped by a backslash for sed to not 10 treat it like separator (at least unless 9 you choose a backslash character as separator).

Depending 8 on the actual application, it might be handy 7 to just escape those characters in both 6 pattern and replacement.

If you're in a bash 5 environment, you can use bash substitution 4 to escape sed separator, like this:

safe_replace () {
    sed "s/${1//\//\\\/}/${2//\//\\\/}/g"
}

It's 3 pretty self-explanatory, except for the 2 bizarre part. Explanation to that:

${1//\//\\\/}
${            - bash expansion starts
  1           - first positional argument - the pattern
   //         - bash pattern substitution pattern separator "replace-all" variant
     \/       - literal slash
       /      - bash pattern substitution replacement separator
        \\    - literal backslash
          \/  - literal slash
            } - bash expansion ends

example 1 use:

$ input="ka/pus/ta"
$ pattern="/pus/"
$ replacement="/re/"
$ safe_replace "$pattern" "$replacement" <<< "$input"
ka/re/ta
Score: 0

Wow. I totally did not know that you could 9 use any character as a delimiter. At least 8 half the time I use the sed and BREs its 7 on paths, code snippets, junk characters, things 6 like that. I end up with a bunch of horribly 5 unreadable escapes which I'm not even sure 4 won't die on some combination I didn't think 3 of. But if you can exclude just some character 2 class (or just one character even)

echo '#01Y $#1+!' | sed -e 'sa$#1+ashita' -e 'su#01YuHolyug'

> > > Holy shit! That's 1 so much easier.

More Related questions