Replace an unknown string within a line using Bash - bash

I want to be able to modify db001 with a string I pass into the command via CLI. At any given time db001 could be a different value so I can't just look for that value.
./myscript modify_db <new value>
myfile.txt
./myscript modify_db mynewdbname002
Before: database_node=db001.mydomain.local
After: database_node=mynewdbname002.mydomain.local
./myscript modify_db db003
Before: database_node=mynewdbname002.mydomain.local
After: database_node=db003.mydomain.local

You can use this sed command inside your script:
sed "s/^\(database_node=\)[^.]*/\1$1/" file
Example:
s='database_node=db001.mydomain.local'
repl() {
sed "s/^\(database_node=\)[^.]*/\1$1/" <<< "$s";
}
and call it as:
repl mynewdbname002
database_node=mynewdbname002.mydomain.local
repl db003
database_node=db003.mydomain.local

You could have a script like, just like below taking an input argument having the replacement value,
#!/bin/bash
perl -lpe "s/database_node=(\w+)/database_node=$1/g" file
and just do
./script.sh newdbname
Use the -i flag for in-place replacement and -i.bak for in-place replacement with a backup of your original file
perl -lpe -i.bak "s/database_node=(\w+)/database_node=$1/g" file
(or) with a simple bash function
function replaceFile() {
perl -lpe -i.bak "s/database_node=(\w+)/database_node=$1/g" file
}

I would avoid trying to produce the new state from the previous state and rather just use a template :
function modify_db() {
echo "database_node=$1.mydomain.local"
}
I use echo here for illustration but you should obviously do whatever you want to do with the "database_node=$1.mydomain.local".
Supposing it should modify the only line starting with database_node from a file db_conf after having printed the old value :
function modify_db() {
echo "Before: $(grep '^database_node=' db_conf)"
sed -i "s/^database_node=.*\.mydomain\.local/database_node=$1.mydomain.local/" db_conf
echo "After: $(grep '^database_node=' db_conf)"
}

Related

Unmask data from matrix linux shell

i have 2 file.
analizeddata.txt:
A001->A002->A003->A004
A001->A005->A007
A022->A033
[...]
and
matrix.txt:
A001|Scott
A002|Bob
A003|Mark
A004|Jane
A005|Elion
A007|Brooke
A022|Meggie
A023|Tif
[..]
How i can replace in analizeddata.txt, or obtain a new file, with the second column of matrix.txt?
The expected output file will be as:
Scott->Bob->Mark->Jane
Scott->Elion->Brooke
Meggie->Tif
[...]
Thanks
Just use sed to replace the string what you want.
sed 's/|/\//g' matrix.txt will generate the replace pattern likes A001/Scott which will be used as regexp/replacement of the second sed s/regexp/replacement/ command.
sed -i option will update directly analizeddata.txt file, back up it before exec this command.
for replace_mode in $(sed 's/|/\//g' matrix.txt); do sed -i 's/'$replace_mode'/g' analizeddata.txt; done
Suggesting awk script:
awk -F"|" 'FNR==NR{arr[$1]=$2;next}{for(i in arr)gsub(i,arr[i])}1' matrix.txt analizeddata.txt
with provided sample data, results:
Scott->Bob->Mark->Jane
Scott->Elion->Brooke
Meggie->A033

how to use variable in perl command into a bash script [duplicate]

When running perl -n or perl -p, each command line argument is taken as a file to be opened and processed line by line. If you want to pass command line switches to that script, how can I do that?
There are three primary ways of passing information to Perl without using STDIN or external storage.
Arguments
When using -n or -p, extract the arguments in the BEGIN block.
perl -ne'BEGIN { ($x,$y)=splice(#ARGV,0,2) } f($x,$y)' -- "$x" "$y" ...
Command-line options
In a full program, you'd use Getopt::Long, but perl -s will do fine here.
perl -sne'f($x,$y)' -- -x="$x" -y="$y" -- ...
Environment variables
X="$x" Y="$y" perl -ne'f($ENV{X},$ENV{Y})' -- ...
Here is a short example program (name it t.pl), how you can do it:
#!/bin/perl
use Getopt::Std;
BEGIN {
my %opts;
getopts('p', \%opts);
$prefix = defined($opts{'p'}) ? 'prefix -> ' : '';
}
print $prefix, $_;
Call it like that:
perl -n t.pl file1 file2 file3
or (will add a prefix to every line):
perl -n t.pl -p file1 file2 file3

read environment variables from whitelist and pipe to sed

I've got a whitelist file of env variables that looks like this:
ENV_A
ENV_B
ENV_C
I have another file filetoreplace.txt that (let's say) looks like this:
asdfasdfasdfasdf{{ENV_A}}asdfasdfasdfasdfasdf
adsfasdf
asdf{{ENV_B}}
asdf{{ENV_A}}
adsfasdfdsfdf{{ENV_C}}
I want to come up with a (one line) sed command that reads the variable names from the file and does the replacement.
For this environment
ENV_A=1
ENV_B=2
ENV_C=3
This would be the output given the above file
asdfasdfasdfasdf1asdfasdfasdfasdfasdf
adsfasdf
asdf2
asdf1
adsfasdfdsfdf3
I think it's kind of similar to this:
< whitelist | while read var; do
sed -i 's/{{'"$var"'}}/'${!var}'/g' filetoreplace.txt
done
Looking for a bit of code golf to do this in a one liner here
Got 2 impractical variants based on your idea with $var\${!var}
First, obvy
vars=( $(cat whitelist) ); for var in ${vars[#]}; { sed "s|{{$var}}|${!var}|g" -i filetoreplace.txt; }
Second, monstrous)
vars=( $(cat filetoreplace.txt) ); for var in ${vars[#]}; { env=${var//[!ENV_ABC]/}; [[ $env ]] && val=${!env} || var=; echo ${var//"{{$env}}"/$val}; }
This is a relatively simple alternative solution :
#!/usr/bin/env bash
bash -c "source whitelist; cat << EOF
$(perl -pe 's/\{(\{.*?})}/\$$1/' filetoreplace.txt)
EOF
"
The aim of the perl script is to transform {{ENV_A}} to ${ENV_A}

How do I replace text using a variable in a shell script

I have a variable with a bunch of data.
text = "ABCDEFGHIJK"
file = garbage.txt //iiuhdsfiuhdsihf]sdiuhdfoidsoijsf
What I would like to do is replace the ] charachter in file with text. I've tried using sed but I keep getting odd errors.
output should be:
//iiuhdsfiuhdsihfABCDEFGHIJKsdiuhdfoidsoijsf
Just need to escape the ] character with a \ in regex:
text="ABCDEFGHIJK"
sed "s/\(.*\)\]\(.*\)/\1$text\2/" file > file.changed
or, for in-place editing:
sed -i "s/\(.*\)\]\(.*\)/\1$text\2/" file
Test:
sed "s/\(.*\)\]\(.*\)/\1$text\2/" <<< "iiuhdsfiuhdsihf]sdiuhdfoidsoijsf"
# output => iiuhdsfiuhdsihfABCDEFGHIJKsdiuhdfoidsoijsf
There is always the bash way that should work in your osx:
filevar=$(cat file)
echo "${filevar/]/$text}" #to replace first occurence
OR
echo "${filevar//]/$text}" #to replace all occurences
In my bash i don't even have to escape ].
By the way, the simple sed does not work?
$ a="AA"
$ echo "garbage.txt //iiuhdsfiuhdsihf]sdiuhdfoidsoijsf" |sed "s/]/$a/g"
garbage.txt //iiuhdsfiuhdsihfAAsdiuhdfoidsoijsf

How to shorten path parts between // in bash

I want my bash prompt paths to be shortened:
~/workspace/project/my-project
# Should be
~/w/p/my-project
This could be achieved by just shortening parts of the path string between // to just the first character.
Is there a way to do this for example in sed?
edit:
Thought someone else looking into this might find what I ended useful so I'm editing it here.
.bashrc:
dir_chomp () {
pwd | sed "s|^$HOME|~|" 2> /dev/null | sed 's:\(\.\?[^/]\)[^/]*/:\1/:g'
}
parse_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
export PS1="\[\033[32m\]\$(dir_chomp)\[\033[33m\]\$(parse_git_branch)\[\033[00m\] $ "
prompt examples (coloring doesn't show):
~/w/e/coolstuff (master) $
~/.c/A/Cache $
If you want to unconditionally shorten all path components, you can do it quite easily with sed:
sed 's:\([^/]\)[^/]*/:\1/:g'
If you want to also insert ~ at the beginning of paths which start with $HOME, you can add that to the sed command (although this naive version assumes that $HOME does not include a colon).
sed 's:^'"$HOME"':~:/;s:\([^/]\)[^/]*/:\1/:g'
A better solution is to use bash substitution:
short_pwd() {
local pwd=$(pwd)
pwd=${pwd/#$HOME/\~}
sed 's:\([^/]\)[^/]*/:\1/:g' <<<"$pwd"
}
With that bash function, you can then "call" it from your PS1 string:
$ PS1='$(short_pwd)\$ '
~/s/tmp$ PS1='\$ '
$
Use PROMPT_COMMAND to set your prompt dynamically each time it is displayed.
shorten_path () {
cwd=${PWD/workspace/w}
cwd=${cwd/project/p}
cwd=${cwd/$HOME/~}
PS1="$cwd "'\$ '
}
PROMPT_COMMAND=shorten_path
This replaces the use of \w escape with custom code to shorten the current working directory. It has the unfortunate side effect of replacing ~ with the name of your home directory, though, which is why the third line is necessary to put it back, if desired.
I use this to shorten to 3 caracters plus "..":
shortpath()
{
dir=${1%/*} && last=${1##*/}
res=$(for i in ${dir//\// } ; do echo -n "${i:0:3}../" ; done)
echo "/$res$last"
}
Version to short to one caracter:
shortpath()
{
dir=${1%/*} && last=${1##*/}
res=$(for i in ${dir//\// } ; do echo -n "${i:0:1}/" ; done)
echo "/$res$last"
}
And then:
export PS1="\$(shortpath \$(pwd)) $"

Resources