-2

I really don't know what I'm doing. In variable a, I want to find the first appearance of '$' after the first appearance of 'Bitcoin', and print everything after it until the first newline. I have the following code:

a = 'something Bitcoin something againe $jjjkjk\n againe something'
if [[ $a =~ .*Bitcoin.*[\$](.*).* ]]; then
    echo "${BASH_REMATCH[1]}" 
else
echo "no"
fi

In this example I would like to get 'jjjkjk'. All I get is 'no'. This code might be really flawed, I have no experience in this. I think tho the problem might be with the '$' sign. Please help!

mpontsasa
  • 11
  • 7
  • Try https://ideone.com/pvPKSE. Note your `a` is not declared correctly, and there is no `$` inside it as it is interpolated. Also, you are trying to use a PCRE regex with Bash, it is not right. `.` here matches any char including newlines. `[\s\S]` matches ``\``, `s` or `S`. – Wiktor Stribiżew Mar 19 '19 at 18:15
  • Ty, this helps a lot. I edited the code, still ot good tho.(Did I edit it right at all?) – mpontsasa Mar 19 '19 at 18:21
  • No, not right, your string has no newline. – Wiktor Stribiżew Mar 19 '19 at 18:33

2 Answers2

2

Properly handle newlines in bash with ANSI-C Quoting -- \n sequences become literal newlines.

a=$'something Bitcoin something againe $jjjkjk\n againe something'
regex=$'Bitcoin[^$]*[$]([^\n]+)'
[[ $a =~ $regex ]] && declare -p BASH_REMATCH
declare -ar BASH_REMATCH='([0]="Bitcoin something againe \$jjjkjk" [1]="jjjkjk")'
# .................................................................^^^^^^^^^^^^

To verify the contents contain newlines:

$ printf '%s' "$regex" | od -c
0000000   B   i   t   c   o   i   n   [   ^   $   ]   *   [   $   ]   (
0000020   [   ^  \n   ]   +   )
0000026
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
-1

Here is a working version of your code:

a='something Bitcoin something againe $jjjkjk\n againe something'
r=".*Bitcoin.*[\$]([^\n]*).*"
if [[ $a =~ $r ]]; then
    echo "${BASH_REMATCH[1]}" 
else
echo "no"
fi

You need to find 'Bitcoin' then find a '$' after it, no matter what is between, so you should use .* operator, also when you want to capture some text until a specific char, the best way is using [^](not) operator, in your case: [^\n] this means capture everything until \n.

Also you had an issue with your variable declaration. a = "..." is not valid, the spaces are waste. so the correct one is 'a=".."`.

Using double quotation is wrong too, this will replaces dollar sign with an empty variable (evaluation)

Saeed Falsafin
  • 556
  • 6
  • 15
  • `[^\n]` matches any char but ``\`` and `n`. It does not match any char but a newline. Besides, `a='something Bitcoin something againe $jjjkjk\n againe something'` has no newline, either. – Wiktor Stribiżew Mar 19 '19 at 18:32
  • If `a` is `'something Bitcoin something $ stuff OP wants to capture $other stuff\n etc`, then matching after `Bitcoin` using `.*` will only match `other stuff`, because `.*` is "greedy" and will consume as much as possible. So perhaps use `[^\$]*` instead of `.*`. – Mike Holt Mar 19 '19 at 18:35
  • @WiktorStribiżew I added the backslash to escape the `$` because he's defining the regex in a double-quoted string. And I'm not suggesting this one change by itself will fix the regex. Only that it will prevent greedily skipping over multiple `$` characters in the input. – Mike Holt Mar 19 '19 at 18:40
  • Yes, but still it won't fix this approach. *`[^\n]` this means capture everything until `\n`* is a mistake. – Wiktor Stribiżew Mar 19 '19 at 18:42
  • @WiktorStribiżew If by "this approach", you mean Saeed's solution in general, then again, I didn't say it would fix the whole solution. My comment only concerns not using `.*` because it might skip over multiple `$` characters. If you're referring to my fix for that, then yes I think my approach would need an additional backslash to differentiate between the character `'$'` and the regex metacharacter `$` which represents the end of a line. But aside from the missing extra backslash, then yes, it does fix the problem of `.*` being too greedy. – Mike Holt Mar 19 '19 at 18:47