**TL;DR** I'd recommend using `${BASH_SOURCE:-$0}` as the most universal variant.

Previous answers are good but they do not mention one caveat of using `${BASH_SOURCE[0]}` directly: if you invoke the script as `sh`'s argument and your `sh` is not aliased to `bash` (in my case, on Ubuntu 16.04.5 LTS, it was linked to `dash`), it may fail with `BASH_SOURCE` variable being empty/undefined. Here's an example:

t.sh:
```
#!/usr/bin/env bash

echo "\$0:                    [$0]"
echo "\$BASH_SOURCE:          [$BASH_SOURCE]"
echo "\$BASH_SOURCE or \$0:    [${BASH_SOURCE:-$0}]"
echo "\$BASH_SOURCE[0] or \$0: [${BASH_SOURCE[0]:-$0}]"
```

(Successful) runs:
```
$ ./t.sh
$0:                    [./t.sh]
$BASH_SOURCE:          [./t.sh]
$BASH_SOURCE or $0:    [./t.sh]
$BASH_SOURCE[0] or $0: [./t.sh]

$ source ./t.sh
$0:                    [/bin/bash]
$BASH_SOURCE:          [./t.sh]
$BASH_SOURCE or $0:    [./t.sh]
$BASH_SOURCE[0] or $0: [./t.sh]

$ bash t.sh
$0:                    [t.sh]
$BASH_SOURCE:          [t.sh]
$BASH_SOURCE or $0:    [t.sh]
$BASH_SOURCE[0] or $0: [t.sh]
```
And finally:
```
$ sh t.sh
$0:                    [t.sh]
$BASH_SOURCE:          []
$BASH_SOURCE or $0:    [t.sh]
t.sh: 6: t.sh: Bad substitution
```

Resume
------
As you see, only the third variant: `${BASH_SOURCE:-$0}` - works and gives consistent result under all invocation scenarios. Note that we take advantage of [bash's feature](https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Arrays "Referencing an array variable without a subscript is equivalent to referencing with a subscript of 0") of making a reference to an unsuscripted array variable equal to the first array element.