Home > Net >  Bash script - Get part of a line of text from another file
Bash script - Get part of a line of text from another file

Time:11-08

I'm quite new to bash scripting. I have a script where I want to extract part of the value of a particular line in a separate config file and then use that value as a variable in the script. For example:

Line 75 in a file named config.cfg

"ssl_cert_location=/etc/ssl/certs/thecert.cer"

I want just the value at the end of "thecert.cer" to then use in the script. I've tried awk and various uses of grep but I can't quite get just the name of the certificate.

Any help would be appreciated. Thanks

These are some examples of the commands I ran:

awk -F "/" '{print $4}' config.cfg
grep -o *.cer config.cfg

Is this possible to extract the value on that line and then edit the output so it just contains the name of the certificate file?

CodePudding user response:

There are many variants, but a simple one that comes to mind with grep is first getting the line, then matching only non-slashes at the end of the line:

<config.cfg grep '^ssl_cert_location=' | grep -o '[^/]*$'

Why didn't your grep command (grep -o *.cer config.cfg) work? Becasue *.cer is a shell glob pattern and will be expanded by the shell to matching file names, even before the grep process is even started. If there are no matching files, it will be passed verbatim, but * in regular expressions is a quantifier which needs a preceeding expression. . in regex is "match any single character". So what you wanted is probably grep -o '.*\.cer', but .* matches anything, including slashes.

An awk solution would look like the following:

awk -F/ '/^ssl_cert_location=/{print $NF}' config.cfg

It uses "/" as separator, finds only lines starting with "ssl_cert_location" and then prints the last (NF) field in from this line.

Or an equivalent sed solution, which matches the same line and then deletes everything including the last slash:

sed -n '/^ssl_cert_location=/s#^.*/##p' config.cfg

To store the output of any command in a variable, use command substitution:

var="$(command with arguments)"

CodePudding user response:

This is a pure Bash version of the basic functionality of basename:

cert=${line##*/}

which removes everything up to and including the final slash. It presupposes that you've already read the line.

Or, using sed:

cert=$(sed -n '75s/^.*\///p' filename)

or

cert=$(sed -n '/^ssl_cert_location=/s/^.*\///p' filename)

This gets the specified line based on the line number or the setting name and replaces everything up to and including the final slash with nothing. It ignores all other lines in the file (unless the setting is repeated in the case of the text match version). The text match version is better because it works no matter what line number the setting is on.

grep uses regular expressions (as does sed). The grep command in your command appears to have a glob expression which won't work. One way to use grep (GNU grep) is to use the PCRE feature (Perl Compatible Regular Expressions):

cert=$(grep -Po '^ssl_cert_location=.*/\K.*' filename)

This works similarly to the sed command.

I have anchored the regular expressions to the beginning of the line. If there may be leading white spaces (the line may be indented), change the regex so it looks something like this:

^[[:space:]]*ssl_cert_location=

which works for both indented and unindented lines.

  • Related