Remove part of $(hostname)') in bash script? - bash

I am running a script to automatically update a field inside a database with the servers hostname
updatevar="UPDATE email_lists SET owneremail = REPLACE(owneremail, 'replacethis321', '$(hostname)');"
However, the hostname is "xyz.com"; how would I make it only be "xyz"? The script needs to remove the ".com" part. This is used on multiple servers so I can't just set it to xyz.

Instead of using $(hostname) directly, assign it to a shell variable so you can use PE expressions at expansion time:
hostname=$(hostname)
updatevar="... ${hostname%%.*} ..."
The use of %%.* trims everything after the first dot. You could instead use ${hostname%.com} if you only wanted to remove the suffix .com (but leave .org, .net, etc alone).
Alternately, instead of $(hostname), use $(hostname -s) if your operating system supports it; this is the "short" form, truncated at the first dot.
That said -- using string substitutions to form SQL expressions is bad form (and since bash doesn't typically give you a way to use bind variables in running SQL, it's usually necessary/appropriate to use a different language if you genuinely want to do the job right). Even the Wooledge bash guide explicitly calls out database interaction as a limitation.

Alternatively you can pipe to awk instead of getting the hostname in a separate variable.
$(hostname | awk -F "." '{print $1}')

Related

Combine two expression in Bash

I did check the ABS, but it was hard to find a reference to my problem/question there.
Here it is. Consider the following code (Which extracts the first character of OtherVar and then converts MyVar to uppercase):
OtherVar=foobar
MyChar=${OtherVar:0:1} # get first character of OtherVar string variable
MyChar=${MyChar^} # first character to upper case
Could I somehow condense the second and third line into one statement?
P.S.: As was pointed out below, not needs to have a named variable. I should add, I would like to not add any sub-shells or so and would also accept a somehow hacky way to achieve the desired result.
P.P.S.: The question is purely educational.
You could do it all-in-one without forking sub-shell or running external command:
printf -v MyChar %1s "${OtherVar^}"
Or:
read -n1 MyChar <<<"${OtherVar^}"
Another option:
declare -u MyChar=${OtherVar:0:1}
But I can't see the point in such optimization in a bash script.
There are more suitable text processing interpreters, like awk, sed, even perl or python if performance matters.
You could use the cut command and put it in a complex expression to get it on one line, but I'm not sure it makes the code too much clearer:
OtherVar=foobar
MyChar=$(echo ${OtherVar^} | cut -c1-1) # uppercase first character and cut string

using bash to loop a script with multiple conditions

I am attempting to add a parameter based on an additional list 'list2.txt' that I have created and I am not quite sure how to implement it.
My running code
while read i
do
sed "s/Pie/$i/g" old_script.sh > new_script.$i.sh
sbatch new_script.$i.sh
done<list.txt
But I want to add the following condition with based on a new list... and I am not quite sure how to implement it into my working script
sed "s/Apple/__/g"
sed allows several ways to supply multiple commands. You can give them individually with -e or just write them into a single script string.
GNU sed allows commands on the same line to be separated with semicolons, and is genrally what you will find, but if you don't have that version you can use embedded newlines. As long as it's quoted it will work fine.
sed "s/Pie/$i/g; s/Apple/__/g;" old_script.sh # GNU specific but common
or
sed "
s/Pie/$i/g
s/Apple/__/g
" old_script.sh # general, should always work.
These are both valid.

Replace a variable every where in a shell script

I need to write a shell script such that I have to read .sh script and find a particular variable (for example, Variable_Name="variable1") and take out is value(variable1).
In other shell script if Variable_Name is used I need to replace it with its Value(variable1)
A simple approach, to build on, might be:
assignment=$(echo 'Variable_Name="variable1"' | sed -r 's/Variable_Name=(.*)/\1/')
echo $assignment
"variable1"
Depending on variable type, the value might be quoted or not, quoted with single apostrophs or quotes. That might be neccessary (String with or without blanks) or superflous. Behind the assignment there might be furter code:
pi=3.14;v=42;
or a comment:
user=janis # Janis Joplin
it might be complicated:
expr="foobar; O'Reilly " # trailing blank important
But only you may know, how complicated it might get. Maybe the simple case is already sufficient. If the new script looks similar, it might work, or not:
targetV=INSERT_HERE; secondV=23
# oops: secondV accidnetally hidden:
targetV="foobar; O'Reilly " # trailing blank important; secondV=23
If the second script is under your control, you can prevent such problems easily. If source and target language are identical, what worked here should work there too.

how to edit url string with sed

My Linux repository file contain a link that until now was using http with a port number to point to it repository.
baseurl=http://host.domain.com:123/folder1/folder2
I now need a way to replace that URL to use https with no port or a different port .
I need also the possibility to change the server name for example from host.domain.com to host2.domain.com
So my idea was to use sed to search for the start of the http until the first / that come after the 2 // thus catching whatever in between and will give me the ability to change both server name port or http\s usage.
Im now using this code (im using echo just for the example):
the example shows how in 2 cases where one time i have a link with http and port 123 converted to https and the second time the other way around
and both code i was using the same sed for generic reasons.
WANTED_URL="https://host.domain.com"
echo 'http://host.domain.com:123/folder1/folder2' | sed -i "s|http.*://[^/]*|$WANTED_URL|"
OR
WANTED_URL="http://host.domain.com:123"
echo 'https://host.domain.com/folder1/folder2' | sed -i "s|http.*://[^/]*|$WANTED_URL|"
is that the correct way doing so?
sed regexes are greedy by default. You can tell sed to consume only non-slashes, like this:
echo 'http://host.domain.com:123/folder1/folder2' | sed -e 's|http://[^/]*|https://host.domain.com|'
result:
https://host.domain.com/folder1/folder2
(BTW you don't have to escape slashes because you are using an alternate separating character)
the key is using [^/]* which will match anything but slashes so it stops matching at the first slash (non-greedy).
You used /.*/ and .* can contain slashes, not that you wanted (greedy by default).
Anyway my approach is different because expression does not include the trailing slash so it is not removed from final output.
Assuming it doesn't really matter if you have 1 sed script or 2 and there isn't a good reason to hard-code the URLs:
$ echo 'http://host.domain.com:123/folder1/folder2' |
sed 's|\(:[^:]*\)[^/]*|s\1|'
https://host.domain.com/folder1/folder2
$ port='123'; echo 'https://host.domain.com/folder1/folder2' |
sed 's|s\(://[^/]*\)|\1:'"$port"'|'
http://host.domain.com:123/folder1/folder2
If that isn't what you need then edit your question to clarify your requirements and in particular explain why:
You want to use hard-coded URLs, and
You need 1 script to do both transformations.
and provide concise, testable sample input and expected output that demonstrates those needs (i.e. cases where the above doesn't work).
wrt what you had:
WANTED_URL="https://host.domain.com"
echo 'http://host.domain.com:123/folder1/folder2' | sed -i "s|http.*://[^/]*|$WANTED_URL|"
The main issues are:
Don't use all-upper-case for non-exported shell variable names to avoid clashes with exported variables and to avoid obfuscating your code (this convention has been around for 40 years so people expect all upper case variables to be exported).
Never enclose any script in double quotes as it exposes the whole script to the shell for interpretation before the command you want to execute even sees it. Instead just open up the single quotes around the smallest script segment possible when necessary, i.e. to expand $y in a script use cmd 'x'"$y"'z' not cmd "x${y}z" because the latter will fail cryptically and dangerously given various input, script text, environment settings and/or the contents of the directory you run it from.
The -i option for sed is to edit a file in-place so you can't use it on an incoming pipe because you can't edit a pipe in-place.
When you let a shell variable expand to become part of a script, you have to take care about the possible characters it contains and how they'll be interpreted by the command given the context the variable expands into. If you let a whole URL expand into the replacement section of a sed script then you have to be careful to first escape any potential backreference characters or script delimiters. See Is it possible to escape regex metacharacters reliably with sed. If you just let the port number expand then you don't have to deal with any of that.

bash find if a variable contains a symbol and escape it

I have written a bash script for Mac OS X that gathers a lot of computer information and writes it to a MySQL database. Everything works fine except one thing. One of the pieces of information I gather is the Computer Name. Probably around 90% of the computers have an apostrophe in their names. The problem is that when I try to write the variable to MySQL it errors out due to the apostrophe.
Is there a way to find if a variable contains an apostrophe and if it does rewrite the variable with the escape character? I am sure I need to use sed but I am still pretty new to this.
For example if I have the following variable:
COMPUTER_NAME="Fred Flintstone's MacBook Air"
How can I change the variable to:
COMPUTER_NAME="Fred Flintstone\'s MacBook Air"
I can pass this off to perl of I need to but I would rather keep it in BASH.
I also don't want to rename the computers because there are over 300 of them.
This will escape apostrophes that are not already escaped:
${COMPUTER_NAME/[^\\]\'/\\\'}
Try doing this to escape what you want :
string="Hello, c'est bientôt l'été ?"
printf '%q\n' "$string"
Output
$'Hello, c\'est bient\303\264t l\'\303\251t\303\251 ?'
You can use Parameter expansion with substitution:
COMPUTER_NAME="${COMPUTER_NAME//\'/\'}"

Resources