0

I have a config file thus:

a: 123
b: abc
device: 1000
c: xyz

[old]
a: 120
b: xyz
device: 200
c: abc

The section "[old]" and everything below it is not always present.

How do I determine if the text "device: 1000" exists in the file BEFORE an optional "[old]" section?

I have been messing around with the following (broken) command syntax and I can't get it to do what I need...

sed -e '0,/^\[/;  /device: /p' configfile ; echo $?

...where 0,/^\[/ was supposed to limit the search between the start of the file and the first occurrence of "[" in the first column. I am trying to get the return code to indicate whether the string was found or not.

1

If awk is an option:

awk 'BEGIN{o=d=1} /\[old\]/{o=0} /device: 1000/&&o==1{d=0;exit} END{exit d}' file

Explanation:

  • BEGIN{o=d=1}: initialize the variables
  • /\[old\]/{o=0} if [old]: is found set o=0
  • /device: 1000/&&o==1{d=0;exit}: if device: 1000 is found and [old] is not found yet, set d=0 and jump to the END{} block without examining the file further.
  • END{exit d}: exit with the given value of d

Run it like this:

awk 'BEGIN{o=d=1} /\[old\]/{o=0} /device: 1000/&&o==1{d=0;exit} END{exit d}' file && echo "contains" || echo "contains not"
  • That'll do nicely. It's about time I learned awk anyway :) – Wossname Oct 26 '18 at 12:32
1

You can look for device: 1000 after having removed everything after [old]:

if sed '/^\[old\]/q' < file | grep -q 'device: 1000'; then
  echo OK
fi

With GNU sed (which you seem to be using given the GNU-specific 0,/.../ in your approach).

if sed -n '/device: 1000/q; /^\[old\]/Q1' < file; then
  echo OK
fi

(q, standard form of Q0 exits with a 0 (success) exit status while Q1 exits with exit status 1 (non-zero, so not success)).

With standard sed, you can't change sed's exit status, but you could rely on whether it outputs something:

if [ -n "$(sed -n '/^\[old\]/q;/device: 1000/!d;=;q' < file)" ]; then
  echo OK
fi

(where = outputs the line number where the first occurrence of device: 1000 is seen).

Or you could use awk which can set the exit status portably:

if awk '$0 == "[old]" {exit 1}; /device: 1000/ {exit 0}' < file; then
  echo OK
fi
0

I typically create a blob with sed by capturing multiple lines to a variable. This allows an inspection later if the required conditional is met.

blob=“$(sed -n “/^abc.*$/,/^$/p” file)”

Now we have the top portion of the file assigned to ”${blob}”.

Now we just conditionally inspect ${blob} of [old] exists:

sh if [ $(grep -c “^\[old/]$” file) -gt 0 ]; then echo “${blob}” | grep “^device” | grep -c 1000 fi

I am sure this can be refactored but this will give you the results you want.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.