Home > OS >  Escape "./" when using sed
Escape "./" when using sed

Time:10-25

I wanted to use grep to exclude words from $lastblock by using a pipeline, but I found that grep works only for files, not for stdout output.

So, here is what I'm using:

lastblock="./2.json"
echo $lastblock | sed '1,/firstmatch/d;/.json/,$d'

I want to exclude ./ and .json, keeping only what is between. This sed command is correct for this purpose, but how to escape the ./ replacing firstmatch so it can work? Thanks in advance!

CodePudding user response:

Use bash's Parameter Substitution

lastblock="./2.json"
name="${lastblock##*/}" # strips from the beginning until last / -> 2.json
base="${name%.*}"       # strips from the last . to the end      -> 2

CodePudding user response:

but I found that grep works only for files, not for stdout output.

here it is. (if your grep supports the -P flag.

lastblock="./2.json"
echo "$lastblock" | grep -Po '(?<=\./).*(?=\.)'

but how to escape the ./

With sed(1), escape it using a back slash \

lastblock="./2.json"
echo "$lastblock" | sed 's/^\.\///;s/\..*$//'

Or use a different delimiter like a pipe |

sed 's|^\./||;s|\..*$||'

with awk

lastblock="./2.json"
echo "$lastblock" | awk -F'[./] ' '{print $2}'

Starting from bashv3, regular expression pattern matching is supported using the =~ operator inside the [[ ... ]] keyword.

lastblock="./2.json"
regex='^\./([[:digit:]] )\.json'
[[ $lastblock =~ $regex ]] && echo "${BASH_REMATCH[1]}"

Although a P.E. should suffice just for this purpose.

CodePudding user response:

I wanted to use grep to exclude words from $lastblock by using a pipeline, but I found that grep works only for files, not for stdout output.

Nonsense. grep works the same for the same input, regardless of whether it is from a file or from the standard input.

So, here is what I'm using:

lastblock="./2.json"
echo $lastblock | sed '1,/firstmatch/d;/.json/,$d'

I want to exclude ./ and .json, keeping only what is between. This sed command is correct for this purpose,

That sed command is nowhere near correct for the stated purpose. It has this effect:

  • delete every line from the very first one up to and including the next subsequent one that matches the regular expression /firstmatch/, AND
  • delete every line from the first one matching the regular expression /.json/ to the last one of the file (and note that . is a regex metacharacter).

To remove part of a line instead of deleting a whole line, use an s/// command instead of a d command. As for escaping, you can escape a character to sed by preceding it with a backslash (\), which itself must be quoted or escaped to protect it from interpretation by the shell. Additionally, most regex metacharacters lose their special significance when they appear inside a character class, which I find to be a more legible way to include them in a pattern as literals. For example:

lastblock="./2.json"
echo "$lastblock" | sed 's/^[.]\///; s/[.]json$//'

That says to remove the literal characters ./ appearing at the beginning of the (any) line, and, separately, to remove the literal characters .json appearing at the end of the line.

Alternatively, if you want to modify only those lines that both start with ./ and end with .json then you can use a single s command with a capturing group and a backreference:

lastblock="./2.json"
echo "$lastblock" | sed 's/^[.]\/\(.*\)[.]json$/\1/'

That says that on lines that start with ./ and end with .json, capture everything between those two and replace the whole line with the captured part alone.

  • Related