BASH - replace with variable contain double quotes inside - bash

I have an text file, with line inside...
line: <version="AAA" email="...ANY..." file="BBB">
new desired line in text file to be: <version="AAA" email="NEW_TEXT" file="BBB">
I want to replace the ...ANY... expression with variable (replace entire line)
I have this script text-file script in #!/bin/bash, but I have problem when expanding double quotes in variables.
LINE_NUMBER="$(grep -nr 'email' *.txt | awk '{print $1}' | sed 's/[^0-9]*//g')"
VAR1="$(grep 'email' *.txt | cut -d '"' -f1-3)"
VAR2="$(grep 'email' *.txt | cut -d '"' -f5-)"
VAR3='NEW_TEXT'
NEW_LINE=$VAR1'"'$VAR3'"'$VAR2
new desired line in text file to be... <version="AAA" email="NEW_TEXT" file="BBB">
awk -i inplace 'NR=='"$LINE_NUMBER"'{sub(".*",'"'$NEW_LINE'"')},1' *.txt
but I get this new line:
<version="" email="NEW_TEXT" file="">
what do I do wrong?
How can I prevent expand duouble quotes inside variable?
please better write me an working example, I had tried other topics, forums, posts....but I have no luck.

You cas use sed :
VAR3='NEW_TEXT'
sed -i "s/email=\"[^\"]*\"/email=\"$VAR3\"/" myfile.xml

Suggesting:
var3="text space % special < chars"
Note var3 may not contain & which is special replacement meaning in sed
sed -E 's|email="[^"]*"|email="'"${var3}"'"|' input.1.txt
Explanation
[^"]* : Match longest string not having " till next ".

Related

convert a file content using shell script

Hello everyone I'm a beginner in shell coding. In daily basis I need to convert a file's data to another format, I usually do it manually with Text Editor. But I often do mistakes. So I decided to code an easy script who can do the work for me.
The file's content like this
/release201209
a1,a2,"a3",a4,a5
b1,b2,"b3",b4,b5
c1,c2,"c3",c4,c5
to this:
a2>a3
b2>b3
c2>c3
The script should ignore the first line and print the second and third values separated by '>'
I'm half way there, and here is my code
#!/bin/bash
#while Loops
i=1
while IFS=\" read t1 t2 t3
do
test $i -eq 1 && ((i=i+1)) && continue
echo $t1|cut -d\, -f2 | { tr -d '\n'; echo \>$t2; }
done < $1
The problem in my code is that the last line isnt printed unless the file finishes with an empty line \n
And I want the echo to be printed inside a new CSV file(I tried to set the standard output to my new file but only the last echo is printed there).
Can someone please help me out? Thanks in advance.
Rather than treating the double quotes as a field separator, it seems cleaner to just delete them (assuming that is valid). Eg:
$ < input tr -d '"' | awk 'NR>1{print $2,$3}' FS=, OFS=\>
a2>a3
b2>b3
c2>c3
If you cannot just strip the quotes as in your sample input but those quotes are escaping commas, you could hack together a solution but you would be better off using a proper CSV parsing tool. (eg perl's Text::CSV)
Here's a simple pipeline that will do the trick:
sed '1d' data.txt | cut -d, -f2-3 | tr -d '"' | tr ',' '>'
Here, we're just removing the first line (as desired), selecting fields 2 & 3 (based on a comma field separator), removing the double quotes and mapping the remaining , to >.
Use this Perl one-liner:
perl -F',' -lane 'next if $. == 1; print join ">", map { tr/"//d; $_ } #F[1,2]' in_file
The Perl one-liner uses these command line flags:
-e : Tells Perl to look for code in-line, instead of in a file.
-n : Loop over the input one line at a time, assigning it to $_ by default.
-l : Strip the input line separator ("\n" on *NIX by default) before executing the code in-line, and append it when printing.
-a : Split $_ into array #F on whitespace or on the regex specified in -F option.
-F',' : Split into #F on comma, rather than on whitespace.
SEE ALSO:
perldoc perlrun: how to execute the Perl interpreter: command line switches

Substitute string with file content in sed

I'm lost trying to do following substitution with sed:
# edit: to capture the full complexity of my problem,
I added the fact that filenames are contained in variables afterwards.
Solutions might therefore directly use the filenames.
given a variable I='insert.txt':
'insert.txt':
Text I wanna skip.
This is text to insert containing
spaces and new lines
given a variable M='toModify.txt':
'toModify.txt':
Insert the new text: here.
I would like to replace the 'here' from $M with the content
of $I:
Insert the new text: This is text to insert containing
spaces and new lines.
I tried:
sed -e "s/here/$(tail -n2 $I | sed -e 's/ /\\ /g' | tr '\n' '\\n')/" $M
with error:
sed unterminated `s' command
The problem is that I don't get the spaces and new lines without terminating the s command.
Any solution?
You can't replace one character with two with tr. Escaping the individual spaces is pointless anyway. The reason for the immediate error is that you end up escaping the final slash, too:
linux$ tail -n2 "$I" | sed -e 's/ /\\ /g' | tr '\n' '\\n'
This\ is\ text\ to\ insert\ containing\spaces\ and\ new\ lines\/
Escaping the spaces is pointless anyway. I guess you want something like this:
linux$ sed '1,2d;$!s/$/\\/' "$I"
This is text to insert containing\
spaces and new lines
We delete lines 1 and two; then add a backslash before every newline except the last.
linux$ sed -e "s/here/$(sed '1,2d;$!s/$/\\/' "$I")/" "$M"
Insert the new text: This is text to insert containing
spaces and new lines.
This is one detail of sed which isn't entirely portable. But the above works for me on Linux and MacOS. (Note you might need to set +H to disable csh-style history expansion aka -bash: !s/$/\\/': event not found errors).
You may use this awk:
awk 'BEGIN{prs=RS; RS=""; getline s < "insert.txt"; RS=prs}
{gsub(/here/, s)} 1' toModify.txt
Insert the new text: This is text to insert containing
spaces and new lines.
Using Perl one-liner
> cat insert.txt
This is text to insert containing
spaces and new lines
> cat toModify.txt
Insert the new text: here
> export I=insert.txt
> export M=toModify.txt
> perl -ne 'BEGIN{$x=qx(cat $ENV{M});$x=~s/here/qx(cat $ENV{I})/e; print $x;exit }'
Insert the new text: This is text to insert containing
spaces and new lines
>

How to get delete word combination "Name Server:" without quotes but keep 'Name Server:someletters/digits' in sed

I have the following lines:
Name Server:NS92.WORLDNIC.COM(or some other value)
Name Server:
Name Server:
Name Server:
Please see the screenshot for better understanding: http://imgur.com/q6Ir4lo
How do I get rid of the 'Name Server:' line but keep the line with the value?
I tried /Name Server:{0,0}/d but it deletes all lines.
Thanks
I was able to get the following two lines to work:
I believe the [:space:] is POSIX compliant:
cat test |sed '/^Name Server:[[:space:] \t]\?$/d'
An alternative is simply:
cat test |sed '/^Name Server:[ \t]\?$/d'
I've also found in sed, that most of the meta-characters (eg + ? ) need to be escaped for sed to recognize them correctly.
This works for me:
echo "Name Server:NS92.WORLDNIC.COM" | sed 's/^Name Server://'
cut -d ":" -f 2 < ff | sed '/^$/d'
Uses ':' as delimiter and splits the line (-d option), then selects the second field (-f option)

Get string between strings in bash

I want to get the string between <sometag param=' and '>
I tried to use the method from Get any string between 2 string and assign a variable in bash to get the "x":
echo "<sometag param='x'><irrelevant stuff='nonsense'>" | tr "'" _ | sed -n 's/.*<sometag param=_\(.*\)_>.*/\1/p'
The problem (apart from low efficiency because I just cannot manage to escape the apostrophe correctly for sed) is that sed matches the maximum, i.e. the output is:
x_><irrelevant stuff=_nonsense
but the correct output would be the minimum-match, in this example just "x"
Thanks for your help
You are probably looking for something like this:
sed -n "s/.*<sometag param='\([^']*\)'>.*/\1/p"
Test:
echo "<sometag param='x'><irrelevant stuff='nonsense'>" | sed -n "s/.*<sometag param='\([^']*\)'>.*/\1/p"
Results:
x
Explanation:
Instead of a greedy capture, use a non-greedy capture like: [^']* which means match anything except ' any number of times. To make the pattern stick, this is followed by: '>.
You can also use double quotes so that you don't need to escape the single quotes. If you wanted to escape the single quotes, you'd do this:
-
... | sed -n 's/.*<sometag param='\''\([^'\'']*\)'\''>.*/\1/p'
Notice how that the single quotes aren't really escaped. The sed expression is stopped, an escaped single quote is inserted and the sed expression is re-opened. Think of it like a four character escape sequence.
Personally, I'd use GNU grep. It would make for a slightly shorter solution. Run like:
... | grep -oP "(?<=<sometag param=').*?(?='>)"
Test:
echo "<sometag param='x'><irrelevant stuff='nonsense'>" | grep -oP "(?<=<sometag param=').*?(?='>)"
Results:
x
You don't have to assemble regexes in those cases, you can just use ' as the field separator
in="<sometag param='x'><irrelevant stuff='nonsense'>"
IFS="'" read x whatiwant y <<< "$in" # bash
echo "$whatiwant"
awk -F\' '{print $2}' <<< "$in" # awk

sed edit of text with variables and special characters

I'm on OS X and writing a bash script to edit text in a file which includes some known text with special characters. There will be a variable too which needs to be retained and some text entered or replaced.
Here is the input file contents:
user_pref("intl.charsetmenu.browser.cache", "UTF-8");
user_pref("network.automatic-ntlm-auth.trusted-uris", "search.co.za");
user_pref("network.cookie.prefsMigrated", true);
I currently have this code:
existingTrusts=`more ~/prefs.js | grep "network.automatic-ntlm-auth.trusted-uris" | awk '{print $2}' | sed 's/);//g' | sed 's/"//g'`
trustSites="company.com,organisation.co.uk,$existingTrusts"
replacementValue='"user_pref("network.automatic-ntlm-auth.trusted-uris", "$trustSites");"'
sed -i 's/^user_pref("network.automatic-ntlm-auth.trusted-uris/$replacementValue/' ~/prefs.js > ~/newPrefs.js
Any help appreciated.
You are using too many pipes to set your existingTrusts variable. Set your variables like this:
existingTrusts=$(awk '/network.automatic-ntlm-auth.trusted-uris/ {gsub(/"|\);/, "", $2); print $2}' ~/prefs.js)
trustSites="company.com,organisation.co.uk,$existingTrusts"
replacementValue='user_pref("network.automatic-ntlm-auth.trusted-uris", "'$trustSites'");'
# and now finally your sed command
sed 's/^user_pref("network.automatic-ntlm-auth.trusted-uris".*$/'"$replacementValue"'/' ~/prefs.js > ~/newPrefs.js
Why so complicated?
trustedSites='company.com,organisation.co.uk,'
sed -i '' -e '/network.automatic-ntlm-auth.trusted-uris/s/, "\([^"]*\)/, "'"${trustedSites}"'\1/' prefs.js
This is imperfect because
It uses unescaped . in a pattern where a literal . is presumed
It presumes , " will appear exactly as that exactly where expected
These things could be fixed.

Resources