I would like to extract substring with sed as below:
#!/bin/bash
txt="[audio.sys.offload.pstimeout.secs]: [3]"
echo $txt|sed -r -e 's/\[[a-zA-Z0-9_.]+\].*/\1/'
expected output is:
audio.sys.offload.pstimeout.secs
Error message:
sed: -e expression #1, char 26: invalid reference \1 on `s' command's RHS
#!/bin/bash
txt="[audio.sys.offload.pstimeout.secs]: [3]"
echo $txt | sed -r -e 's/^\[(.*)\]:.*/\1/'
we're grabbing all the characters from the 1st [ until the last ]: and putting them in a capture group.
Would you like the regex to remain mostly like yours?
by the way - with lazy matching (which isn't supported by sed),
the regex could be cleaner, simply ^\[(.*?\])
Related
I am trying to extract the version information a string using sed as follows
echo "A10.1.1-Vers8" | sed -n "s/^A\([0-9]+\)\.\([0-9]\)\.[0-9]+-.*/\1/p"
I want to extract '10' after 'A'. But the above expression doesn't give the expected information. Could some one please give some explanation on why this statement doesn't work ?
I tried the above command and changed options os sed but nothing works. I think this is some syntax error
echo "A10.1.1-Vers10" | sed -n "s/^X\([0-9]+\)\.\([0-9]\)\.[0-9]+-.*/\1/p"
Expected result is '10'
Actually result is None
$ echo "A10.1.1-Vers8" | sed -r 's/^A([[:digit:]]+)\.(.*)$/\1/g'
10
Search for string starting with A (^A), followed by multiple digits (I am using POSIX character class [[:digit:]]+) which is captured in a group (), followed by a literal dot \., followed by everything else (.*)$.
Finally, replace the whole thing with the Captured Group content \1.
In GNU sed, -r adds some syntactic sugar, in the man page, it is called as --regexp-extended
GNU grep is an alternative to sed:
$ echo "A10.1.1-Vers10" | grep -oP '(?<=^A)[0-9]+'
10
The -o option tells grep to print only the matched characters.
The -P option tells grep to match Perl regular expressions, which enables the (?<= lookbehind zero-length assertion.
The lookbehind assertion (?<=^A) ensures there is an A at the beginning of the line, but doesn't include it as part of the match for output.
If you need to match more of the version string, you can use a lookforward assertion:
$ echo "A10.1.1-Vers10" | grep -oP '(?<=^A)[0-9]+(?=\.[0-9]+\.[0-9]+-.*)'
10
This sed works, to replace the value for Java home in a shell script:
sed -i 's#^JAVA_HOME=.*$#JAVA_HOME="/usr/lib/jvm/java-1.7.0-oracle.x86_64"#' /apps/tempbsu.sh
but now I am trying to use/invoke that sed from inside a Perl app, using qx():
qx(sed -i 's#^JAVA_HOME=.*$#JAVA_HOME="/usr/lib/jvm/java-1.7.0-oracle.x86_64"#' /apps/tempbsu.sh);
and when I do that, I am getting an error:
sed: -e expression #1, char 58: unterminated `s' command
From checking, I gather that error is happening because the sed is missing the last delimiter, but it seems like it is correct, i.e.:
sed -i 's#.....#.......#' /apps/tempbssu.sh
Can someone tell me why this sed is failing with I use in a qx() in Perl?
$#JAVA_HOME is treated as a Perl variable (the number of the last element of the array variable). Escape it: \$#JAVA_HOME
$ echo "haha#nihao" | sed "s/#.+$/end/"
haha#nihao
I want to match contents between character # and the end of line.why can't i get it?
:%!sed "s/#.\+$/end/"
E194:No alternate file name to substitute for '#'
problem 1:
why i can't use it in sed of vim?
problem 2:
how to see the EORROR 194 ?
problem 1: why i can't use it in sed of vim?
Because by default sed uses BRE, basic regular expressions:
/.+/ this matches any character followed by a "+"
/.\+/ this matches one or more occurrences of any character
You can tell sed to use extended regular expressions with the -r flag in GNU implementations and -E flag with BSD implementations:
$ echo "haha#nihao" | sed -r "s/#.+$/end/"
hahaend
problem 2: how to see the EORROR 194 ?
You get this error because # has a special meaning in vim when you run commands with !: # marks on the command line are replaced with the alternate file. It should work if you escape the #:
%!sed "s/\#.\+$/end/"
You can read about this error with the :help E194 command, and about alternative file with :help alternate-file.
use sed -r
echo "haha#nihao" | sed -r "s/#.+$/end/"
hahaend
from man sed
-r, --regexp-extended
use extended regular expressions in the script.
I have a config file I need to change (again) and the line is
set wrapper_code=C:\windows\drivers\cache
I need to change it to
set wrapper_code=/home/harry/solo/run
I wrote
cat Proxy.bat | sed -i.bk -e 's/\(^set wrapper_home\=\).*/\/home/'1${dbuser}'/gateway/service\' Proxy.bat
I get an error message
sed: -e expression #1, char 37: unknown option to `s'
What is wrong with my code string
If you are using / as the pattern separator is sed, you have to escape the slashes in the strings (paths). To avoid it, use a different separator:
sed -i.bk -e 's%\^set wrapper_code=C:\\windows\\drivers\\cache%set wrapper_code=/home/harry/solo/run%' Proxy.bat
You also have to escape backslashes, as they have a special meaning in sed.
The cat part is useless.
I'd like to replace all the \r\n with < br/ >in a document, and I'm trying this see script below
# sed -i 's/\r\n/<br/>' ~/xxd/*
however i got this error back
sed: -e expression #1, char 12: unknown option to `s'
How do i solve this problem?
Thanks!
Your problem is that you have the / separator in your replacement string so sed is assuming that's the end of your replacement, and that the > following it is a flag.
If your sed is modern enough, just use a different separator character, one that's not in the replacement string:
pax$ echo hello | sed -e 's/e/<br />/'
sed: -e expression #1, char 9: unknown option to `s'
pax$ echo hello | sed -e 's?e?<br />?'
h<br />llo
Alternatively, you can escape the offending character but I try to avoid that since it tends to lead to overly sawtooth sed commands like /\/\/\/\/\/\.
The other thing you may want to watch out for is trying to use \n in your regex since sed operates on lines anyway. If your intent is to just strip carriage returns and insert HTML line breaks, then the following sed command may be better:
s?\r$?<br />?