9

I'm having trouble getting sed to recognize both hyphen and underscore in its pattern string.

Does anyone know why

[a-z|A-Z|0-9|\-|_]

in the following example works like

[a-z|A-Z|0-9|_]

?

$  cat /tmp/sed_undescore_hypen
lkjdaslf lkjlsadjfl dfpasdiuy service-type = service-1; jaldkfjlasdjflk address = address1; kldjfladsf
lkjdaslf lkjlsadjfl dfasdf  service-type = service_1; jaldkfjlasdjflk address = address1; kldjfladsf

$  sed 's/.*\(service-type = [a-z|A-Z|0-9|\-|_]*\);.*\(address = .*\);.*/\1    \2/g' /tmp/sed_undescore_hypen
lkjdaslf lkjlsadjfl dfpasdiuy service-type = service-1; jaldkfjlasdjflk address = address1; kldjfladsf
service-type = service_1    address = address1

$  sed 's/.*\(service-type = [a-z|A-Z|0-9|\-]*\);.*\(address = .*\);.*/\1    \2/g' /tmp/sed_undescore_hypen
service-type = service-1    address = address1
lkjdaslf lkjlsadjfl dfasdf  service-type = service_1; jaldkfjlasdjflk address = address1; kldjfladsf

$  sed 's/.*\(service-type = [a-z|A-Z|0-9|_]*\);.*\(address = .*\);.*/\1    \2/g' /tmp/sed_undescore_hypen
lkjdaslf lkjlsadjfl dfpasdiuy service-type = service-1; jaldkfjlasdjflk address = address1; kldjfladsf
service-type = service_1    address = address1
Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
techie11
  • 1,243
  • 15
  • 30

4 Answers4

14

As mentioned, you don't need anything to separate your ranges in a bracket expression. All that will do is adding | to the characters matched by the expression.

Then, to add a hyphen, you can put it as the first or last character in the expression:

[a-zA-Z0-9_-]

And finally, ranges like a-z don't necessarily mean abcd...xyz, depending on your locale. You could use a POSIX character class instead:

[[:alnum:]_-]

Where [:alnum:] corresponds to all alphanumeric characters of your locale. In the C locale, it corresponds to 0-9A-Za-z.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
0

You don't need to use | symbol in a regex character class to separate the characters. Perhaps try something like this ...

[a-zA-Z0-9\-_]
m87
  • 4,445
  • 3
  • 16
  • 31
0
$ sed 's/.*\(service-type = [a-z|A-Z|0-9|_-]*\);.*\(address = .*\);.*/\1    \2/g' sed_underscore_hypen.txt
service-type = service-1    address = address1
service-type = service_1    address = address1

pknga_000@miro MINGW64 ~/Documents
$ sed 's/.*\(service-type = [-a-z|A-Z|0-9|_]*\);.*\(address = .*\);.*/\1    \2/g' sed_underscore_hypen.txt
service-type = service-1    address = address1
service-type = service_1    address = address1

To match a hyphen in a character class, it must not be placed between two characters, otherwise it will be interpreted as a range operator. So to match a hyphen, place it at the beginning or end of the character class: and no escaping is necessary. See this answer for explanation: https://stackoverflow.com/a/4068725

Community
  • 1
  • 1
Phillip Ngan
  • 15,482
  • 8
  • 63
  • 79
0

In my case, I wanted to replace a config setting that included a hyphen. Surrounding the setting in .* worked:

sed 's/.*some-service.*/some-service="new-value"/g' file

Also works when the config setting has an underscore.

Steve Chavez
  • 931
  • 10
  • 13