0

Can someone please take the following statements:

kernelHash=$(grep -m 1 -o '"uImage-[0123456789.]*-ts-armv7l": [^, }]*' $SecureBootJson | sed 's/^.*: //')

kernelHash=$(grep -oP '"uImage-[0123456789.]*-ts-armv7l.*?\btype\b"' $SecureBootJson | cut -f3 -d ' ' | sed 's/,//')

and break them down for me and explain what they are supposed to accomplish?

Bishop Minter
  • 107
  • 1
  • 3
  • 11
  • Match `"uImage-`, followed by any number of characters present in the set of `0123456789.`, followed by `-ts-armv7l": `, followed by any number of characters present in the set `^, }` **AND** Match `"uImage-`, followed by any number of characters present in the set of `0123456789.`, followed by `-ts-armv7l`, followed by any number of non-newline characters (but as few as possible until the next token is matched), followed by a word boundary (`(^\w|\w$|\W\w|\w\W)` without consuming a character), followed by `type`, followed by another word boundary and finally by `"`. – ctwheels Sep 14 '17 at 20:04

1 Answers1

3

Both are setting a variable kernelHash based on the value of the file whose name/path is stored in the variable $SecureBootJson. I will assume you understand what the pipes | are doing.

Grep

man grep helps us parse the arguments to grep:

  • -m 1: Stop reading a file after 1 matching line
  • -o: Print only the matched (non-empty) parts of a matching line
  • -P: Interpret the regex as a Perl regex

Grep regexes

'"uImage-[0123456789.]*-ts-armv7l": [^, }]*'

Matches a "key": value pair

  1. "uImage-: literally
  2. [0123456789.]*: zero or more digits or dots
  3. -ts-armv7l":: literally
  4. [^, }]*: zero or more characters that are not ,, or }

and

'"uImage-[0123456789.]*-ts-armv7l.*?\btype\b"'

Matches a "quoted" string

  1. "uImage-: literally
  2. [0123456789.]*: zero or more digits or dots
  3. -ts-armv7l: literally
  4. .*?: lazily matches zero or more non-newline characters
  5. \btype\b": Matches the word 'type' using word boundaries

cut

cut -f3 -d ' '

From man cut:

  • -f3: return the 3rd field
  • -d ' ': split on single spaces

So this cut command splits the string on spaces and returns the 3rd section.

The sed commands

sed 's/^.*: //'

Replaces all non-newline characters between the beginning of the line the rightmost ': ' with nothing. Assuming the grep left us with a "key": value line where value does not contain ': '(which it cannot thanks to grep), we are left with value.

sed 's/,//'

Replaces the first , found in the string with nothing.

Note

There are a number of quirks and opportunities for improvement in these commands, but I have not included them in the main body of the answer, because the question was "what does this do?". My foremost suggestion would be the use of jq to parse Json.

Will Barnwell
  • 4,049
  • 21
  • 34
  • `.*: ` is greedy, so it would replace everything up until the last `: ` in the line. Not really important here, but it does make the `^` anchor at the beginning of the line unnecessary. Something like `^[^:]*: ` would make more sense. – stevesliva Sep 14 '17 at 21:29
  • A very thorough explanation! And helpful. Thanks Will. – Bishop Minter Sep 15 '17 at 11:33