Sed error : bad option in substitution expression - linux

I have a configuration file (gpsd.default) containing data with the following format:
# If you must specify a non-NMEA driver, uncomment and modify the next line
GPSD_SOCKET="/var/run/gpsd.sock"
GPSD_OPTIONS=""
GPS_DEVICES=""
I am making a change on the file with sed:
sed -i 's/^GPS_DEVICES="".*/GPS_DEVICES="dev/ttyUSB1"/' /etc/default/gpsd.default
or
sed -i '4s/^.*/GPS_DEVICES="dev/ttyUSB1"/' /etc/default/gpsd.default
The above sed command returns error:
sed: bad option in substitution expression
Because the new line contains "/" in its expression.
How to update my sed command to make it work?

This is because you are using a regex containing /, which is the same character sed uses as delimiter.
Just change the sed delimiter to another one, for example ~:
sed -i 's~^GPS_DEVICES="".*~GPS_DEVICES="dev/ttyUSB1"~' /etc/default/gpsd.default
By the way, since you are changing files in /etc, you may want to use -i.bak, so that the original file gets backed up. It is a good practice to prevent loss of important information.

You should update your sed command to this.
sed -i 's/^GPS_DEVICES=\"\".*/GPS_DEVICES=\"dev\/ttyUSB1\"/' /etc/default/gpsd.default

Related

Not getting replaced using the sed using the sed -i command

I am trying to do the following thing using the sed
cp src/config/template.js src/config/index.js
export API_GATEWAY_ENDPOINT="http://localhost:9000/"
sed -i "" "s|{{API_GATEWAY_ENDPOINT}}|$API_GATEWAY_ENDPOINT|g" src/config/index.js
But when I run this script, then I am getting this error,
sed: can't read s|{{API_GATEWAY_ENDPOINT}}|http://localhost:9000/|g: No such file or directory
I am using a Linux machine.
Can any tell me why this is happening?
The first argument to sed should be the script. So when you have that extra "", the second argument is interpreted as a file name.
And you don't need to copy the file and then do an inplace replacement. Instead use > operator to redirect the output from sed to the proper file.
>src/config/index.js <src/config/template.js sed "s|{{API_GATEWAY_ENDPOINT}}|$API_GATEWAY_ENDPOINT|g"

Sed how to find and replace a value using a bash variable [duplicate]

I have a configuration file (gpsd.default) containing data with the following format:
# If you must specify a non-NMEA driver, uncomment and modify the next line
GPSD_SOCKET="/var/run/gpsd.sock"
GPSD_OPTIONS=""
GPS_DEVICES=""
I am making a change on the file with sed:
sed -i 's/^GPS_DEVICES="".*/GPS_DEVICES="dev/ttyUSB1"/' /etc/default/gpsd.default
or
sed -i '4s/^.*/GPS_DEVICES="dev/ttyUSB1"/' /etc/default/gpsd.default
The above sed command returns error:
sed: bad option in substitution expression
Because the new line contains "/" in its expression.
How to update my sed command to make it work?
This is because you are using a regex containing /, which is the same character sed uses as delimiter.
Just change the sed delimiter to another one, for example ~:
sed -i 's~^GPS_DEVICES="".*~GPS_DEVICES="dev/ttyUSB1"~' /etc/default/gpsd.default
By the way, since you are changing files in /etc, you may want to use -i.bak, so that the original file gets backed up. It is a good practice to prevent loss of important information.
You should update your sed command to this.
sed -i 's/^GPS_DEVICES=\"\".*/GPS_DEVICES=\"dev\/ttyUSB1\"/' /etc/default/gpsd.default

Sed not working in usual way - Shell scripting

I have two sed command which includes in my cook.sh script. One command is
sed -E -i "s/^(\\\$mainDomain=\")[^\"]+(\";)$/\1$MainDomain\2/" /var/config.php
This is working fine.
But the below command which is almost same. But it is not working.
sed -E -i "s/^(\\\$authURI=\")[^\"]+(\";)$/\1$duo_auth\2/" /var/config.php
That give the below error message
sed: -e expression #1, char 36: unknown option to `s'
Any idea on this ?
The issue is likely due to your replacement variable $duo_auth having a un-escaped /, change the default sed separator from / to ~ as
sed -E -i "s~^(\\\$authURI=\")[^\"]+(\";)$~\1$duo_auth\2~" /var/config.php
Try it without -i for seeing if the replacement is as expected and put it back after confirmation.
Example:-
cat /var/config.php
<?php
$authURI="dev.digin.io";
now setting the variable
duo_auth="http://auth.uri.digin.io:3048/"
Now the replacement, without -i
sed -E "s~^(\\\$authURI=\")[^\"]+(\";)$~\1$duo_auth\2~" /var/config.php
<?php
$authURI="http://auth.uri.digin.io:3048/";
The problem is probably due to $duo_auth containing an unescaped /. This means that the sed editing script will have a syntax error.
You may pick any other character to use as a delimiter in the s/.../.../ command, for example #:
sed "s#....#....#"
Just make sure that you pick a character that is not ever going to turn up in either $duo_auth or $authURI.
While testing, I'd recommend that you avoid using in-place-editing (-i) with sed. Also, the -i switch is horribly non-portable between sed implementations (some requires an argument).
Instead, do the slightly more cumbersome
sed -e "s#...#...#" data.in >data.in.tmp && mv -f data.in.tmp data.in
While testing, check the data.in.tmp file before moving it.

Add a kernel parameter with sed to grub

I'm writing a bash script to non-interactively enable hibernation on a linux system. To this end, I need to insert a shell variable that contains slashes on a specific line of a while, inside quotes that are on that line.
The relevant part of the file to b edited looks like this:
GRUB_DEFAULT=0
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="Manjaro"
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
GRUB_CMDLINE_LINUX=""
I need to change it to this:
GRUB_DEFAULT=0
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="Manjaro"
GRUB_CMDLINE_LINUX_DEFAULT="quiet resume=/dev/disk/by-partuuid/c5a552c2-fe8f-423a-9037-c35bf090d9c3"
GRUB_CMDLINE_LINUX=""
The added parameter is provided by a shell variable.
I tried this:
sed -i '\*^GRUB_CMDLINE_LINUX_DEFAULT* s*"$* '"$(grub_resume_boot_option)"'"*' /etc/default/grub
Logic that I was aiming for was: "Look for a line that starts with pattern "GRUB_CMDLINE_LINUX_DEFAULT", and replace the last " with the given pattern. Use * as delimiter to preserve the slashes in the expanded variable."
However, the command fails if there are any spaces at the end of the line. Is there any way to make it not take spaces at the end of the line into account?
Also, if there is more simple or readable solution to this, I would be very interested.
You can do:
sed -i 's#^\(GRUB_CMDLINE_LINUX_DEFAULT="quiet\)"$#\1 resume=/dev/disk/by-partuuid/c5a552c2-fe8f-423a-9037-c35bf090d9c3"#' /etc/default/grub
Example:
$ sed 's#^\(GRUB_CMDLINE_LINUX_DEFAULT="quiet\)"$#\1 resume=/dev/disk/by-partuuid/c5a552c2-fe8f-423a-9037-c35bf090d9c3"#' <<<'GRUB_CMDLINE_LINUX_DEFAULT="quiet"'
GRUB_CMDLINE_LINUX_DEFAULT="quiet resume=/dev/disk/by-partuuid/c5a552c2-fe8f-423a-9037-c35bf090d9c3"
From: https://serverfault.com/questions/885684/editing-the-value-of-grub-cmdline-linux-default-thru-bash-script
sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT="/&newstuff /' /etc/default/grub
This will add "newstuff" to the beginning of the list of params. Examples:
sed 's/^GRUB_CMDLINE_LINUX_DEFAULT="/&newstuff /' <<< 'GRUB_CMDLINE_LINUX_DEFAULT="quiet"'
GRUB_CMDLINE_LINUX_DEFAULT="newstuff quiet"
sed 's/^GRUB_CMDLINE_LINUX_DEFAULT="/&newstuff /' <<< 'GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"'
GRUB_CMDLINE_LINUX_DEFAULT="newstuff quiet splash"
sed -i "s/GRUB_CMDLINE_LINUX_DEFAULT="[^"]*/& $(grub_resume_boot_option)/" /etc/default/grub

replace unknown line in file linux command

I am trying to change a line with a pattern in a textual file using Linux bash.
I tried the sed command:
sed -i 's/old/new/' < file.txt
The issue with this command line I have to specify the exact "old" word. I want to change thousands of files where the old word has a pattern like this: old1(, old2(,old3(,....old10000(
I would like to change the oldxxx( in all files to old1(
Any ideas how to do this?
You can use something like:
sed -i 's/old[0-9]\{1,\}(/old1(/' file.txt
This matches "old" followed by one or more digits and a "(" and replaces it with "old1(".
If your version of sed supports extended regular expressions, you can use:
sed -r -i 's/old[0-9]+\(/old1(/' file.txt
instead, which does the same thing. On some versions of sed, the -E switch is used instead of -r.
If you have more than one instance of the pattern "oldXX(" on the same line, you may also want to the g modifier (s/.../.../g) to do a global replacement.

Resources