How to read a variable from file, modify and safe it to an other variale - linux

What I want:
There is a file /scripts/backup/config.cfg which contains variables. In my specific case the important ones are:
BACKUPLOCATION=""
ROOTLOCATION="/backup"
Then there is a script /scripts/backup/performBackup.sh
For a specific reason I want a part of the script do the following operations:
read the value of the variable ROOTLOCATION
add a ("/" and) timestamp (Date&Time)
safe the new created value to BACKUPLOCATION (by replacing its current value)
Example
If this is the previous state of the config.cfg:
BACKUPLOCATION="dummy"
ROOTLOCATION="/backup"
After the script ran it should be:
BACKUPLOCATION="/backup/2020-05-02-23-00"
ROOTLOCATION="/backup/"
What I tried
First of all the config file gets "loaded" using
source /scripts/backup/config.cfg
I then tried to use the sed command but the quotes are messing with me. Here is one try (which didn't work):
sed -i 's/BACKUPLOCATION\=.*/BACKUPLOCATION="'$ROOTLOCATION/$(date +%Y-%m-%d-%H-%M)'"/' /scripts/backup/config.cfg

Try this:
source /scripts/backup/config.cfg
sed -i 's|BACKUPLOCATION=.*|BACKUPLOCATION="'"$ROOTLOCATION/$(date +%Y-%m-%d-%H-%M)"'"|' /scripts/backup/config.cfg
The problem with your sed is that you use / as delimiter, which is present in $ROOTLOCATION after expansion, therefore sed fails. I used |, which is usually is not present in filenames. If you ever create a file with |, that sed will fail too! So, "know your data" :)

Related

bash: How to replace an entire line in a text file by a part of its content

I have a text file, called texto.txt in Documentos folder, with some values like the ones below:
cat ~/Documentos/texto.txt
65f8: Testado
a4a1: Testado 2
So I want to change a whole line by using a customized function which gets as parameters the new value.
The new value will always keep the first 6 characters, changing only what comes after them. Although I am testing only the first four.
Then I edited my .bashrc including my function like shown below.
muda()
{
export BUSCA="$(echo $* | cut -c 1-4)";
sed -i "/^$BUSCA/s/.*/$*/" ~/Documentos/texto.txt ;}
When I run the command below it works like a charm, but I feel it could be improved.
muda a4a1: Testado 3
Result:
cat ~/Documentos/texto.txt
65f8: Testado
a4a1: Testado 3
Is there a smarter way to do this? Maybe by getting rid of BUSCA variable?
I'd write:
muda() {
local new_line="$*"
local key=${newline:0:4}
sed -i "s/^${key//\//\\/}.*/${new_line//\//\\/}/" ~/Documentos/texto.txt
}
Notes:
using local variables, not exported environment variables
does not call out to cut, bash can extract a substring
escaping any slashes in the variable values so the sed code is not broken.

Linux sed replacing word in generic way

I would like to do a sed command in Linux to uncomment the "#auth"
Original file
#%PAM-1.0
auth sufficient pam_rootok.so
# Uncomment the following line to implicitly trust users in the "wheel" group.
#auth sufficient pam_wheel.so trust use_uid
I can write this command to do it:
sed 's/#auth.*sufficient.*pam_wheel.so trust use_uid/auth\t sufficient\t pam_wheel.so trust use_uid/' /etc/pam.d/su
But I think it is too long. Is there any better way to do this (more generic)?
I don't want to specific the line number to replace it, because if someone changed the file, the script will not run normally.
For example:
Search keyword "#auth.*sufficient.*pam_wheel.so trust use_uid", if found, replace this the word "#auth" to "auth", and then append the later wording in the line
With GNU sed, look up the -i option that allows in-place modification and then anchor the regular expression. For instance:
sed -i '/^#auth.*pam_wheel/s/^#//' INPUTFILE
will look for lines beginning with "#auth" that include "pam_wheel" later on the line and replace the "#" at the beginning with nothing.

How to Use "sed" Bash Command

I am having difficulties replacing a string in c program file with the content of a variable in a bash file. The idea is to copy the address of Linux kernel sys_call_table and then use it in my C program to intercept system calls. I found a couple of examples online, but none of them have worked for me so far. So any help will be greatly appreciated.
Here is the content of my bash file, "bashFile.sh"
TABLE=$(grep sys_call_table /boot/System.map-$(uname -r) |awk '{print $1}')
sed -i "s/myTABLE/{$TABLE}/g" my_LKM.c
When I run "sudo sh bashFile.sh" command, nothing happen. The string myTable in C file does not get replaced. However, when I try the following variation:
TABLE=$(grep sys_call_table /boot/System.map-$(uname -r) |awk '{print $1}')
sed -i 's/myTABLE/{$TABLE}/g' my_LKM.c
the myTABLE string get replaced with {$TABLE} instead of the content of the variable TABLE (sys_call_table address). I tried debugging with "echo $TABLE" to see if TABLE content is the address of sys_call_table and it worked. So, I concluded that the problem might be the syntax of sed command. However, I do not know how to fix it at this time. Thank you in advance for your help.
P.S. Below is the content of myLKM.c file:
unsigned long *sys_call_table;
sys_call_table = (unsigned long *)myTABLE;
First of all, don't use sudo to run this. It doesn't magically make things work. If you need root privileges to edit source code you're working on, you have serious problems with your development setup.
Use double-quotes if you want stuff to expand inside them. e.g.
TABLE=$(awk '/sys_call_table/ {print $1}' /boot/System.map-$(uname -r))
sed -i "s/myTABLE/${TABLE}UL/g" my_LKM.c
As karakfa suggested, make sure you try this without -i first. His other suggestion, of expanding $TABLE in an unquoted context, instead of inside double quotes, was terrible, though. You need the entire string to be part of the same sed arg, so just ending the single quotes is bad.
Also, I guess he misread {$TABLE} for ${TABLE}, and simplified to $TABLE. Or actually, from the context of your question, it looks like you want a plain numeric constant, not wrapped in braces. So you should use $TABLE.
Actually, you should use ${TABLE}UL so it's an unsigned-long integer literal. Without those modifiers, an address that didn't fit in the low32 would probably get mangled before the cast to a pointer type was applied.
You have to escape the quotes
sed -i 's/myTABLE/'$TABLE'/g' my_LKM.c
obviously try first NOT in-place (remove -i)

Understanding sed

I am trying to understand how
sed 's/\^\[/\o33/g;s/\[1G\[/\[27G\[/' /var/log/boot
worked and what the pieces mean. The man page I read just confused me more and I tried the info sai Id but had no idea how to work it! I'm pretty new to Linux. Debian is my first distro but seemed like a rather logical place to start as it is a root of many others and has been around a while so probably is doing stuff well and fairly standardized. I am running Wheezy 64 bit as fyi if needed.
The sed command is a stream editor, reading its file (or STDIN) for input, applying commands to the input, and presenting the results (if any) to the output (STDOUT).
The general syntax for sed is
sed [OPTIONS] COMMAND FILE
In the shell command you gave:
sed 's/\^\[/\o33/g;s/\[1G\[/\[27G\[/' /var/log/boot
the sed command is s/\^\[/\o33/g;s/\[1G\[/\[27G\[/' and /var/log/boot is the file.
The given sed command is actually two separate commands:
s/\^\[/\o33/g
s/\[1G\[/\[27G\[/
The intent of #1, the s (substitute) command, is to replace all occurrences of '^[' with an octal value of 033 (the ESC character). However, there is a mistake in this sed command. The proper bash syntax for an escaped octal code is \nnn, so the proper way for this sed command to have been written is:
s/\^\[/\033/g
Notice the trailing g after the replacement string? It means to perform a global replacement; without it, only the first occurrence would be changed.
The purpose of #2 is to replace all occurrences of the string \[1G\[ with \[27G\[. However, this command also has a mistake: a trailing g is needed to cause a global replacement. So, this second command needs to be written like this:
s/\[1G\[/\[27G\[/g
Finally, putting all this together, the two sed commands are applied across the contents of the /var/log/boot file, where the output has had all occurrences of ^[ converted into \033, and the strings \[1G\[ have been converted to \[27G\[.

replace a line in linux file containing special characters

Here is an extract from a script showing the variables for the script
PathToPiconPNG="/var/OscamSrvidPicon/picon/19.2E/"
PathToOscamSrvid="/var/OscamSrvidPicon/picon/19.2E/oscam.srvid"
PathToPiconTPL="/var/OscamSrvidPicon/oscam_picons/"
PathToTmp="/tmp/"
I want to run this script numerous times replacing (for example) this line:
PathToPiconPNG="/var/OscamSrvidPicon/picon/19.2E/"
with this lines
PathToPiconPNG="/var/OscamSrvidPicon/picon/28.2E/"
I have tried using sed (I know this example is wrong but you might get what im trying to achieve)
sed 's/{PathToPiconPNG="/var/OscamSrvidPicon/picon/19.2E/"}/{PathToPiconPNG="/var/OscamSrvidPicon/picon/28.2E/"}/g' filename.txt > newfilenam.txt
If that is not possible, is there any way that I can set the variable externally from another script
sed -E 's/picon\/.+\//picon\/28.2E\//' filename.txt > newfilenam.txt

Resources