Assumed one has a string containing parameters:
echo "-v foo -d --print bar-foo ba-z fOo"
How can one get parameters beginning with a dash?
-v -d --print
An alternative:
STR="-v foo -d --print bar-foo ba-z fOo"
echo "$STR" | egrep -o -e "(^| )+--?[^ ]+" | sed -e 's/ //g'
Will output:
-v
-d
--print
If you want to parse options passed to your script, you should consider using getopt.
References:
example of how to use getopts in bash
$ str="-v foo -d --print bar-foo ba-z"
$ for i in $str; do test ${i::1} = - && echo $i; done
-v
-d
--print
Note this is an instance where you must not quote the variable, since you want word splitting to occur. (That is, do not write for i in "$str")
Related
I need to get a number of version from file. My version file looks like this:
#define MINOR_VERSION_NUMBER 1
I try to use sed command:
VERSION_MINOR=`sed -i -e 'MINOR_VERSION_NUMBER\s+\([0-9]+\).*/\1/p' $WORKSPACE/project/common/version.h`
but I get error:
sed: -e expression #1, char 2: extra characters after command
The "address" that selects matching lines needs to be enclosed in /.../ (or \X...X for any X).
sed -ne '/MINOR_VERSION_NUMBER/{ s/.*\([0-9]\).*/\1/;p }'
Don't use -i, it changes the file in place and doesn't output anything.
The more common way would be to use awk to find the line and extract the wanted column:
awk '(/MINOR_VERSION_NUMBER/){print$3}'
using grep
grep MINOR_VERSION_NUMBER | grep -o '[0-9]*$'
Demo :
$echo "#define MINOR_VERSION_NUMBER 1" | grep -o '[0-9]*$'
1
$echo "#define MINOR_VERSION_NUMBER 1123" | grep -o '[0-9]*$'
1123
$
Here is a correction of your attempt. Change your line:
VERSION_MINOR=`sed -i -e 'MINOR_VERSION_NUMBER\s+\([0-9]+\).*/\1/p' $WORKSPACE/project/common/version.h`
into:
VERSION_MINOR=`sed -n -e '/^#define\s\+MINOR_VERSION_NUMBER\s\+\([0-9]\+\).*/ s//\1/p' $WORKSPACE/project/common/version.h`
This can be made more readable with GNU sed's -r option:
VERSION_MINOR=`sed -n -r -e '/^#define\s+MINOR_VERSION_NUMBER\s+([0-9]+).*/ s//\1/p' $WORKSPACE/project/common/version.h`
As stated by choroba, awk would be more suited than sed for this kind of processing (see his answer).
However, here is another solution using bash's read builtin, together with GNU grep:
read x x VERSION_MINOR x < <(grep -F -w -m1 MINOR_VERSION_NUMBER $WORKSPACE/project/common/version.h)
VERSION_MINOR=$(echo "#define MINOR_VERSION_NUMBER 1" | tr -s ' ' | cut -d' ' -f3)
How do I grep strings in between nested brackets using bash? Is it possible without the use of loops? For example, if I have a string like:
[[TargetString1:SomethingIDontWantAfterColon[[TargetString2]]]]
I wish to grep only the two target strings inside the [[]]:
TargetString1
TargetString2
I tried the following command which cannot get TargetString2
grep -o -P '(?<=\[\[).*(?=\]\])'|cut -d ':' -f1
With GNU's grep P option:
grep -oP "(?<=\[\[)[\w\s]+"
The regex will match a sequence of word characters (\w+) when followed by two brackets ([[). This works for your sample string, but will not work for more complicated constructs like:
[[[[TargetString1]]TargetString2:SomethingIDontWantAfterColon[[TargetString3]]]]
where only TargetString1 and TargetString3 are matched.
To extract from nested [[]] brackets, you can use sed
#!/bin/bash
str="[[TargetString1:SomethingIDontWantAfterColon[[TargetString2]]]]"
echo $str | grep -o -P '(?<=\[\[).*(?=\]\])'|cut -d ':' -f1
echo $str | sed 's/.*\[\([^]]*\)\].*/\1/g' #which works only if string exsit between []
Output:
TargetString1
TargetString2
You can use grep regex grep -Eo '\[\[\w+' | sed 's/\[\[//g' for doing this
[root#localhost ~]# echo "[[TargetString1:SomethingIDontWantAfterColon[[TargetString2]]]]" | grep -Eo '\[\[\w+' | sed 's/\[\[//g'
TargetString1
TargetString2
[root#localhost ~]#
Starting with a string like:
String=1973251922:197325192278:abcdefgh:0xfff689990:Searching done for the string:SUCCESS.
A regular expression needed for matching all strings after the 4th colon ":" and assigning it for a variable in shell script like:
var_result="Searching done for the string:SUCCESS."
Using shell (bash or POSIX)
$ string="1973251922:197325192278:abcdefgh:0xfff689990:Searching done for the string:SUCCESS."
$ echo "${string#*:*:*:*:}"
Searching done for the string:SUCCESS.
${string#*:*:*:*:} is an example of prefix removal. It removes a prefix consisting of four colon-separated strings.
The output can be saved in a shell variable:
$ var_result=${string#*:*:*:*:}
$ echo "$var_result"
Searching done for the string:SUCCESS.
Using cut
cut works for this:
$ string="1973251922:197325192278:abcdefgh:0xfff689990:Searching done for the string:SUCCESS."
$ cut -d: -f 5- <<<"$string"
Searching done for the string:SUCCESS.
The above selects the fifth field and all succeeding fields where fields are separated by colons. More specifically, -d: tells cut to use : as the field separator and -f 5- tells it to select field 5 and everything after.
To save the output in a variable, we use command substitution:
$ var_result=$(cut -d: -f 5- <<<"$var")
$ echo "$var_result"
Searching done for the string:SUCCESS.
If you just have a POSIX shell, not bash, then we need to use echo:
$ var_result=$(echo "$var" | cut -d: -f 5-)
$ echo "$var_result"
Searching done for the string:SUCCESS.
Or, safer still, printf:
$ var_result=$(printf "%s" "$var" | cut -d: -f 5-)
$ echo "$var_result"
Searching done for the string:SUCCESS.
Using sed
The following uses sed to remove the first four fields defined by colons:
$ sed -E 's/([^:]*:){4}//' <<<"$string"
Searching done for the string:SUCCESS.
More specifically:
[^:] matches any character except :.
[^:]*: matches any number of non-colons followed by a colon.
([^:]*:){4} matches exactly four colon separated fields.
s/([^:]*:){4}// is a substitute command which looks for the first four colon-separated columns and replaces them with an empty string.
The following is the same but saves the result in a variable:
$ var_result=$(sed -E 's/([^:]*:){4}//' <<<"$string")
$ echo "$var_result"
Searching done for the string:SUCCESS.
The following is the same but good also for POSIX shells:
$ var_result=$(printf '%s' "$var" | sed -E 's/([^:]*:){4}//')
$ echo "$var_result"
Searching done for the string:SUCCESS.
Following solution may help you on same.
Let's say following is the variable's value:
var="1973251922:197325192278:abcdefgh:0xfff689990:Searching done for the string:SUCCESS."
echo "$var"
1973251922:197325192278:abcdefgh:0xfff689990:Searching done for the string:SUCCESS.
echo "$var" | awk -F":" '{$1=$2=$3=$4="";sub(/^:+/,"");print $0}' OFS=":"
Searching done for the string:SUCCESS.
With bash regex you can say:
String="1973251922:197325192278:abcdefgh:0xfff689990:Searching done for the string:SUCCESS."
if [[ $String =~ ^([^:]*:){4}(.+)$ ]]; then
echo ${BASH_REMATCH[2]}
fi
In bash I need to shave a first and/or last character from string, but only if it is a certain character.
If I have | I need
/foo/bar/hah/ => foo/bar/hah
foo/bar/hah => foo/bar/hah
You can downvote me for not listing everything I've tried. But the fact is I've tried at least 35 differents sed strings and bash character stuff, many of which was from stack overflow. I simply cannot get this to happen.
what's the problem with the simple one?
sed "s/^\///;s/\/$//"
Output is
foo/bar/hah
foo/bar/hah
In pure bash :
$ var=/foo/bar/hah/
$ var=${var%/}
$ echo ${var#/}
foo/bar/hah
$
Check bash parameter expansion
or with sed :
$ sed -r 's#(^/|/$)##g' file
How about simply this:
echo "$x" | sed -e 's:^/::' -e 's:/$::'
Further to #sputnick's answer and from this answer, here's a function that would do it:
STR="/foo/bar/etc/";
STRB="foo/bar/etc";
function trimslashes {
STR="$1"
STR=${STR#"/"}
STR=${STR%"/"}
echo "$STR"
}
trimslashes $STR
trimslashes $STRB
# foo/bar/etc
# foo/bar/etc
echo '/foo/bar/hah/' | sed 's#^/##' | sed 's#/$##'
assuming the / character is the only one you're trying to remove, then sed -E 's_^[/](.*)_\1_' should do the job:
$ echo "$var1"; echo "$var2"
/foo/bar/hah
foo/bar/hah
$ echo "$var1" | sed -E 's_^[/](.*)_\1_'
foo/bar/hah
$ echo "$var2" | sed -E 's_^[/](.*)_\1_'
foo/bar/hah
if you also need to replace other characters at the start of the line, add it to the [/] class. for example, if you need to replace / or -, it would be sed -E 's_^[/-](.*)_\1_'
Here is an awk version:
echo "/foo/bar/hah/" | awk '{gsub(/^\/|\/$/,"")}1'
foo/bar/hah
I cannot figure out how to make this work:
I have:
icon-braille icon-bookmark-empty icon-blogger icon-adult icon-address-book
And I want:
'icon-braille','icon-bookmark-empty','icon-blogger','icon-adult','icon-address-book'
This is OSX friendly sed "s/ /','/g;s/^/'/;s/$/'/":
$ echo "icon-braille icon-bookmark-empty" | sed "s/ /','/g;s/^/'/;s/$/'/"
'icon-braille','icon-bookmark-empty'
With shell and sed:
echo "'"$(sed "s/ /','/g")"'"
Example:
$ echo "'"$(sed "s/ /','/g")"'"
icon-braille icon-bookmark-empty icon-blogger icon-adult icon-address-book
'icon-braille','icon-bookmark-empty','icon-blogger','icon-adult','icon-address-book'
The first line was inserted, the second — produced.
$ echo "icon-braille icon-bookmark-empty icon-blogger icon-adult icon-address-book" | sed -e "s/ \+/','/g" -e "s/^/'/" -e "s/$/'/"
'icon-braille','icon-bookmark-empty','icon-blogger','icon-adult','icon-address-book'
You can just use the shell (assuming bash)
$ list="icon-braille icon-bookmark-empty icon-blogger icon-adult icon-address-book"
$ result=""; sep=""
$ for word in $list; do result+=$sep\'$word\'; sep=,; done
$ echo "$result"
'icon-braille','icon-bookmark-empty','icon-blogger','icon-adult','icon-address-book'