tags:

views:

171

answers:

2

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):

  1. Ignore # char in the beginning of line
  2. Match first the param string
  3. Second match the "a b c d e f g z x w" (like grep -w) and give exit status if success

Something like ....

sed "/^ *#/b; /\<param\>/"  ....
A: 

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).

Jonathan Leffler
Sorry but I need first to match the paramand if match second to mach the "a b c d e f g z x w"yael
yael
sed must to match separately the param and the "a b c d e f g z x w" because some times param string have some space between "=" separatoryael
yael
somthing like:sed -i "/^ *#/b; /\<$PARAM\>/ NEED TO MATCH a b c d e f g z x w"
yael
example how it should be from grep :grep -v '^ *#' yaron | grep -w param3 yaron | grep -w "tgtgtrgbvtybhtyb"need the same from sed any suggestions?
yael
any suggestions?
yael
A: 

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 whitespace
  • AND 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 ...) ]]
Dennis Williamson