6

I'm currently using this one-liner to get the latest release version of docker-compose.

curl --silent "https://api.github.com/repos/docker/compose/releases/latest" | grep "tag_name" | sed -E 's/.*"([^"]+)".*/\1/'

This isn't my code.  I copied & pasted it, and it worked, and I wanted to learn more.  Specifically, I am very interested in the sed command.  Can anyone help me understand it better?

sed -E 's/.*"([^"]+)".*/\1/'

Essentially I don't understand any of the string.  I know the items individually (.* = any character one or more, [^"] = accept anything that isn't ").  But when it is written in that way I am unsure how it works out.

Output of command without the sed command: "tag_name": "1.22.0",

Output of command with the sed command: 1.22.0

6
  • 1
    which sed? my gnu sed, does not have -E Commented Jul 31, 2018 at 9:16
  • 1
    Which parts of regex are you struggling with? What do you understand so far? Commented Jul 31, 2018 at 9:17
  • 1
    @ctrl-alt-delor GNU sed has supported -E (a la BSD) for a while now (4.2 in 2009) even though it was initially undocumented (documented in 4.3 2017). -E is going to make it to the POSIX standard. GNU sed had -r initially for that. Commented Jul 31, 2018 at 9:19
  • 1
    It may make more sense to use a JSON parsing tool here. Like jq -r .tag_name. Commented Jul 31, 2018 at 9:20
  • Yes jq will be more stable, as json can be formatted onto one line etc etc etc. Commented Jul 31, 2018 at 9:24

2 Answers 2

15

sed -E 's/.*"([^"]+)".*/\1/

  • -E: sed will use Extended Regex
  • 's': to substitute value.
  • /: the separator of pattern and replacement that will be use.
  • .*"([^"]+)".*: the best way I know to explain regex is a graph:
    regex explantation
    Basically it matches every line that have two block of quotes and put the second one (without the quotes) inside group one.
  • /: separator between your regexp and your replacement
  • \1: replace your original line with the group number 1 : 1.22.0 in this case.
  • /: last separator without option after it so it will replace only once a line.

Hope this is explain well enough.
If you need to read a regex in a more visual way you can use the site regexper which is amazing.

2
  • 2
    This is wrong. The regex does not match every line that has two blocks of quotes; it matches every line that has two or more quote characters (so it could be just a single pair).  And it doesn’t capture the second “block of quotes”; it captures the last one.  To be more precise, it captures whatever is between the last two quotes; it will capture c from a"b"c"d, even though that doesn’t make much sense. Commented Jul 10, 2020 at 20:38
  • 1
    @G-ManSays'ReinstateMonica' minor correction: it matches every line that has two or more double quotes, with at least 1 character in between them that is not also a double quote. It cannot just be a single pair (echo \"\" | sed -E 's/.*"([^"]+)".*/foo/' does not print foo)
    – Z4-tier
    Commented Jun 16, 2021 at 19:30
6

I don't know what you know about sed.  In sed(1) you may find:

sed - stream editor for filtering and transforming text

and:

-E, -r, --regexp-extended

        use extended regular expressions in the script (for portability use POSIX -E).

In sed you could define, let me say, word pattern between parentheses and you could substitute them with \ (backslash) followed by a one-digit number.  In your question, let me write as below:

echo '"tag_name": "1.22.0"' | sed -E 's/"([a-z]+\_[a-z]+)": "([0-9\.]+)"/\2/'
  • -E use extended regular expressions
  • 's/Part1/Part2/ the main structure
  • " regex pattern starts with "
  • ([a-z]+\_[a-z]+) first word pattern contains two part of chars joined with _
  • ": " after that these sequence symbols would occur
  • ([0-9\.]+) the second word pattern contains one or more digits with .
  • " pattern ends with it.
  • \2 now you call the second word pattern
2
  • The question asks about a specific sed command, and you present a similar command and explain it.  Why not just answer the question? Commented Jul 10, 2020 at 20:40
  • because he told:'Can anyone help me understand it better?' and knew somethings of Regex. Commented Jul 11, 2020 at 5:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .