6 ms·
Elegant, but not something you should ever use outside of ad-hoc situations. I think this is more comprehensible, and is also more robust because it actually s
by bspammer 4y ago
Elegant, but not something you should ever use outside of ad-hoc situations.
I think this is more comprehensible, and is also more robust because it actually specifies the field you're looking for rather than just any line with quotes:
gawk -F'"' '/^ name:/ {print $2}' appVersion.gradle
(hacker news is clobbering the spaces after ^)
- ISL 4y agoThat's way more comprehensible and maintainable.
- layer8 4y agoIt’s a pity that awk doesn’t support capture groups in line patterns. Then you could get rid of the field separator and make the script even more comprehensible. (You can simulate this with match() in gawk, but then you must know how match() works.) Personally, I’d probably rather use sed here: sed -nE 's/^\s*name:\s*"([^"]*)"\s*$/\1/p" While that regex is more complex, it is also safer and more explicit.
- nine_k 4y agoGnu ask does support them. MacOS cli userland is less capable by default.
- layer8 4y agoYou can't reference the results of capture groups in line patterns in gawk, unless you use the match() function. You can write: match($0, /...(...).../, arr) { ...refer to arr[i]... } But you can't write: /...(...).../ { ...refer to a capture group somehow... }
- asicsp 4y agoGrep is often better suited for extracting matched portion, especially if you also have PCRE option: grep -oP -m1 'name:\s*"\K[^"]+'
- olsgaarddk 4y agoI thought I was pretty good at regex, but I could never have written this one and had to consult both `man grep` and regex101.com. Explanations for the beginner and intermediate regex and grep user: `-o`: Only return the match, instead of the entire line `-P`: use Perl compatible regex `-m` max-count, Stop reading a file after NUM matching lines. And now for the regex: `name:`: find the exact match `\s*"`: Zero or more spaces leading up to and including an double quote `\K`: This was the kicker for me. "resets the starting point of the reported match. Any previously consumed characters are no longer included in the final match" - basically tells the regex engine that the characters _before_ `\K` needs to be there in order to form a match, but it should only return the characters _after_ `\K` as the match. This is super handy! Is there a "reverse \K"? `[^"]+`: One or more characters that are not a double quote. This basically means "Find the line that has a key called "name" and return all the characters after the first double quote and until the last double quote"
- asicsp 4y agoIf you'd like to learn more about such grep powers, check out my free ebook [0] What do you mean by "reverse \K"? Are you aware of lookarounds? Perhaps you meant positive lookahead? # match digits only if there is a semicolon afterwards $ echo '12; 42,31;100' | grep -oP '\d+(?=;)' 12 31 [0] https://learnbyexample.github.io/learn_gnugrep_ripgrep/introduction.html https://learnbyexample.github.io/learn_gnugrep_ripgrep/intro...
- mxmkm 4y agoIn vim there is `\zs` and `\ze` where `\zs` is the `\K` equivalent in grep. Basically :%s/hello \zsworld\ze out there/planet/g would find all `hello world out there` and replace `world` to `planet`.
- Joker_vD 4y agoConsider this: grep -P 'start: (\d+) end' "How do I make it print only the captured group with the number, not the whole line?" is a pretty common Stack Overflow question. The "\K" thing gets rid of the "start: " part, but what about " end"? That's were "reverse \K" would come in handy.
- Izkata 4y ago> (hacker news is clobbering the spaces after ^) Indent with 2 spaces to get code formatting: https://news.ycombinator.com/formatdoc https://news.ycombinator.com/formatdoc
- sorcercode 4y agoNice! I think your solution is definitely more legible. The key to legible awk I’ve found is to not rely on the defaults that awk assumes. (but it’s quite the mental exercise to decipher it). Feels like regex but less painful
- nerdponx 4y agoMost of my AWK scripts are actually standalone scripts, as with `#!/usr/bin/awk -f` of similar. It's actually a very readable and comfortable little language once you free yourself from the one-liner constraint.
- chii 4y agoif you used a regex to match a line, would it run slower than just via the field separator, and count the NF? On a tiny file the speed won't matter at all - but on a big file (let's say, you're looking thru log files with hundreds of gigs in size).
- Someone 4y agoThe regex solution might be faster. The $0=$2 solution has to find the second field and test it for truthiness for every line, while the regex one only has to do that for those matching the regex, and matching that regex will be fast for most lines (skipping spaces and then testing for a fixed string ‘name’ is easy) Regardless, the regex solution is more robust and maintainable. Depending on how this get used, I might add code to detect the ‘appVersion’ start and end lines, set/clear a flag there and only match the ‘name’ lines when that flag is set to make it even more robust (who knows what other lines might contain ‘name’ now or in the future?)