sed as grep + ignore # and match
I have the following file example
more somefile
param=a b c d e f g z x w
# param=a b c d e f g z x w
I need to create with sed the following (should be one line if possible):
- Ignore # char in the beginning of line
- Match first the param string
- Second match the "
a b c d e f g z x w
" (like grep -w) and give ex开发者_运维百科it status if success
Something like ....
sed "/^ *#/b; /\<param\>/" ....
You can do AND
conditions in sed
by using nested curly braces:
sed -n '/\<param\>/ { /^[[:space:]]*#/ ! { /\<a \+b \+c \+d \+e \+f ... \>/ p}}'
This says a line matches if:
- it contains the word param
AND
does not (!
) start with a comment character after any whitespaceAND
has a "word" which consists of a sequence of characters separated by one or more spaces
To test for success, you will need to see if the result is a not null string:
if [[ -n $(sed ...) ]]
The first term deletes lines with a '#' at the start. It isn't clear why you want two terms to match the param and trailing material (why not one?). It isn't clear whether you want the matching lines printed or not. And it isn't clear that you can get an exit status from sed indicating whether any rows matched the pattern or not - you get told whether it was able to execute the script and open all the files, but that's all. With all those caveats, then:
sed -n '/^#/d;/param=a b c d e f g z x w/p' somefile
This prints the lines that match, ignoring (-n
) those that do not.
If there are spaces permitted around the '=' sign, you can modify the search pattern to allow for that:
sed -n '/^#/d;/param *= *a b c d e f g z x w/p' somefile
It isn't clear whether the spacing inside the 'value' part is critical; if it is not, then you can use appropriate '*
' (space, space, star; the markup editor is working too hard again) terms to allow for variable white space.
However, if you want a grep-like status, you probably need to use grep
. As I noted - sed
does not return status for 'pattern found' or 'pattern not found' because that is not what it is concerned with.
If you truly want sed
to do two matches, then you have to get into the grouping operations, which are no longer a single-line script.
sed -n '/^#/d;/param/{
/a b c d e f g z x w/p
}' somefile
This says:
- Delete lines starting with '#'.
- When you find a line containing 'param',
- Do a separate match for the 'a b c...' line, only printing the result if it is found.
NB: as written, the first pattern match will find 'xyz=param' and 'parameter = a b c' too; if that's not what you want, modify the pattern appropriately. The second pattern will also find 'g h i a b c d ... x w'; if that is not what you want, you have to modify it appropriately.
I think you might be better off using sed to strip the comment and blank lines, and then using your grep sequence to find your values. You must be using GNU grep
; POSIX-standard versions of grep
on other machines (Solaris, AIX, HP-UX, etc) do not support the -w
option. Even with the grep sequence, you have not distinguished between lines such as:
param=a b c d e f g z x w
a b c d e f g z x w=param
Also, none of this allows leading blanks before the parameter name, and none of it allows for tabs instead of blanks. Also, there must be room for suspicion that even if the parameter name is fixed, the value may vary on occasion; making that into a usable shell script (that invokes sed or grep or both) adds to the details to be considered.
- Search the given files (arguments 3 onwards) for entries of the general form 'name = value', where name is argument 1 and value is argument 2, ignoring comment lines that start with a '#', and allowing variable spacing (but no tabs) around the name and the equals; there must be no data before or after the value.
This leads to:
if [ $# -lt 3 ]; then echo "Usage: $0 name value file [...]" 1>&2; exit; fi
name=$1
value=$2
shift 2
sed -n -e '/^#/d' -e "/ *$name *= *$value *$/p" "$@"
Now, if this script is called paramfinder
, I can write:
paramfinder param 'a b c d e f g z x w' somefile
I can also write:
paramfinder param '.*a b c d *e f g *z x w.*' somefile
Note that I've passed regular expression metacharacters into the sed script in the value.
Note that it will break if I pass:
paramfinder passwordfile /etc/passwd somefile
That's because the slashes in "/etc/passwd" break up the regular expression matching.
Depending on your real requirements (is it homework or a production problem - and how robust does it have to be), you might consider moving to Perl somewhere about here (or Python, or other similar scripting language of your choosing).
精彩评论