I'm new in bash script and trying to replace some words in my file using sed. Following is the bash I use in my script:
sed -i '' "s/<pre>.*<\/pre>/<pre>($NEWNAME) $MD5<\/pre>/"~/Desktop/replace.html
And I got error message saying: bad flag in substitute command: 'U'. I use double quote because I need to put variables in.
My environment is Mac.
======================================
1.Turns out I forgot to leave a space between replace string and file name. Which led to the result always showing: bad flag in substitute command: '~'. It works now.
2.The reason is I used MD5=$(md5 path) to create MD5 value which gets the reault of MD5 (path) *****, and the path contains / which breaks the regex. After changing MD5=$(md5 -q path), it will be ok.
Most likely your $NEWNAME variable has a forward slash in it, which is being used as regex delimiter in sed. Try this sed with an alternate delimiter e.g. ~:
sed -i '' "s~<pre>.*</pre>~<pre>($NEWNAME) $MD5</pre>~" ~/Desktop/replace.html
Related
I am new to linux and any bash scripts and have the following problem:
I have this kryptokey:
-----BEGIN CERTIFICATE-----\n
MIICSTCCAfCgAwIBAgIRAMsLZqD4PavC7NJz7+5ld+EwCgYIKoZIzj0EAwIwdjEL\n
MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG\n
cmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHzAdBgNVBAMTFnRs\n
c2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTgxMjMxMTA1ODA5WhcNMjgxMjI4MTA1\n
ODA5WjB2MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE\n
BxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEfMB0G\n
A1UEAxMWdGxzY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49\n
AwEHA0IABEbH7l3CiqLA4N4wgfilYgyEuxDrMAqDX6BrFOfWhymNosjh5FlJDHtN\n
GPDKhjtrI6e1q0NC0l6wh9h9TrBn7N2jXzBdMA4GA1UdDwEB/wQEAwIBpjAPBgNV\n
HSUECDAGBgRVHSUAMA8GA1UdEwEB/wQFMAMBAf8wKQYDVR0OBCIEIH7OaekSLJda\n
S0yuV9PCsuasGTt/+/35aVBXTVbII2rCMAoGCCqGSM49BAMCA0cAMEQCIEd+YP/6\n
tCzG/LueYTEio8ApQSyz94ju07pmc3LZJDKBAiALu66LKhOpKhogY9XEFg4TScOt\n
el4dC6OnMMTmRsEtoA==\n-----END CERTIFICATE-----\n
saved in a file $replacementOrg1 (is the path to that file).
Now I want to replace in a template $file "INSERT_ORG1_CA_CERT" with this certificate and safe it in $org1. But I need to keep the "\n" Character.
The result should keep the \n and write it into one line.
I already tried:
sed -e "s#INSERT_ORG1_CA_CERT#$(cat $replacementOrg1)#g" $file > $org1
but it interprets the "\n" as new line.
So the final Output should look like this, 1 String in 1 Line:
"-----BEGIN CERTIFICATE-----\nMIICSTCCAfCgAwIBAgIRAMsLZqD4PavC7NJz7+5ld+EwCgYIKoZIzj0EAwIw djEL\nMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG\ncmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHzAdBgNVBAMTFnRs\nc2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTgxMjMxMTA1ODA5WhcNMjgxMjI4MTA1\nODA5WjB2MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE\nBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEfMB0G\nA1UEAxMWdGxzY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49\nAwEHA0IABEbH7l3CiqLA4N4wgfilYgyEuxDrMAqDX6BrFOfWhymNosjh5FlJDHtN\nGPDKhjtrI6e1q0NC0l6wh9h9TrBn7N2jXzBdMA4GA1UdDwEB/wQEAwIBpjAPBgNV\nHSUECDAGBgRVHSUAMA8GA1UdEwEB/wQFMAMBAf8wKQYDVR0OBCIEIH7OaekSLJda\nS0yuV9PCsuasGTt/+/35aVBXTVbII2rCMAoGCCqGSM49BAMCA0cAMEQCIEd+YP/6\ntCzG/LueYTEio8ApQSyz94ju07pmc3LZJDKBAiALu66LKhOpKhogY9XEFg4TScOt\n
el4dC6OnMMTmRsEtoA==\n-----END CERTIFICATE-----\n"
Anybody can help?
Thank you
That is not a valid key. What someone has done is "half-encoding" (I don't know a better term) the newlines - they have added the literal string "\n" before every newline. What you very likely want is either the original key with no "\n" strings or a single line string where every newline has been replaced with "\n".
With the original value you can use replace instead - it supports newlines in the replacement value:
$ replace foo $'foo\nbar' <<< $'x\nfoo\ny'
x
foo
bar
y
Your case should be simply replace 'INSERT_ORG1_CA_CERT' "$(< $replacementOrg1)" "$file" > "$org1".
The substitute command isn't very good with multi-line replacement strings. But we can use GNU sed's read command to work around that:
echo "${replacementOrg1}" |
sed -e '/INSERT_ORG1_CA_CERT/{r /dev/stdin' -e ';d}' ${file} > ${org1}
How it works:
echo the multi-line string, piping it to /dev/stdin.
When sed finds the target "INSERT_ORG1_CA_CERT" it reads /dev/stdin and outputs the contents
then deletes the search string line, (which is presumed to contain no other text).
The tricky part is the inadequately documented r command -- sed assumes everything after the r is part of the filename. If we tried '/INSERT_ORG1_CA_CERT/{r /dev/stdin;d}' it would bomb with the error:
unmatched '{'
Because sed would think the filename was literally "/dev/stdin;d}". But the error message doesn't complain about the missing file, because sed never complains about a missing r filename. Instead sed complains that there's no } closing brace, because sed thinks the } is part of the filename.
To avoid that error we stick an ' -e ' in there.
For substitution of a phrase I simply use:
sed -i "s:phrase_to_be_matched*:phrase_to_be_replaced_with:g" file_name
This works fine, until i have the following problem:
I have a line in a file,
#$ModLoad imudp
What i want,
$ModLoad imudp
I am currently running this,
sed -i "s:.*$ModLoad imudp.*:$ModLoad imudp:g" file
But i am getting:
imudp
I know, this is happening because, $ModLoad imudp is considered as a variable, and as it doesn't exist I am getting this output.
I have tried with "$ModLoad imudp" too, but got the same result.
I can't simply remove the# because, i have other commented line in my file.
How to resolve this?
Try using single quotes '' instead of double quotes.
sed -i 's:.*$ModLoad imudp.*:$ModLoad imudp:g' file
This prevents special meaning of $ for variable expansion.
Edit: (as per #tripleee's comment)
Also escape $ for matching literal dollar sign
sed -i 's:.*\$ModLoad imudp.*:$ModLoad imudp:g' file
What I want to achieve:
Suppose I have a file file with the following content:
ENV_VAR='/foo/`whoami`/bar/'
sh my_script.sh 'LOL'
I want to replace - using sed - the single quotes that surrounds the directory names, but not the ones that surrounds stuff that does not seem like a directory, for example, the arguments of a script.
That is, after running the sed command, I would expect the following output:
ENV_VAR="/foo/`whoami`/bar/"
sh my_script.sh 'LOL'
The idea is to make this happen without using tr to replace ' with ", nor sed like s/'/"/g, as I don't want to replace the lines that does not seem to be directories.
Please note that sed is running on AIX, so no GNU sed is available.
What I have tried:
If I use sed like this:
sed "s;'=.*/.*';&;g" file
... the & variable hold the regex previously matched, that is: ='/foo/`whoami`/bar/'. However, I can't figure out how to make the replacement so the single quotes gets transformed into double quotes.
I wonder if there's a way to make this work using sed only, via a one-liner.
This will do the job:
/usr/bin/sed -e "/='.*\/.*'/ s/'/\"/g" file
Basically, you just want the plain ' => " replacement, but not for all lines, just for those that match the pattern ='.*\/.*'/. And, in the s command you just need to escape the ".
This should work:
sed "s/'\(.*\/.*\)'/\"\1\"/g"
Captures the part between ' and uses a backreference.
Im trying to extract the last line of a text file using sed and move it to a variable. However, command substitution using quotes breaks the sed command which already uses quotes.
sed '$!d' cookie.txt
Returns: localhost FALSE /XSS/ FALSE ****** loggedIn No
However, trying to move it to a variable, like so:
varin='sed '$!d' cookie.txt'
provides no output for the variable $varin
For PHP, we can have nested quotes using double and single quotes, is there anything similar here?
Try this:
var=$(tail -1 cookie.txt)
or with sed:
var=$(sed '$!d' cookie.txt)
If you are getting an error like "localhost:command not found" with $(...), it sounds like you are nesting backticks inside the command substitution, like
variable=$(`sed '$!d' cookie.txt`)
The backticks would run the sed command to produce the string beginning with "localhost", then because that string is inside $(...), it would be treated as a command to run. Simply using
variable=$( sed '$!d' cookie.txt )
should do what you want.
I found a solution for extracting the password from a Mac OS X Keychain item. It uses sed to get the password from the security command:
security 2>&1 >/dev/null find-generic-password -ga $USER | \
sed -En '/^password: / s,^password: "(.*)"$,\1,p'
The code is here in a comment by 'sr105'. The part before the | evaluates to password: "secret". I'm trying to figure out exactly how the sed command works. Here are some thoughts:
I understand the flags -En, but what are the commas doing in this example? In the sed docs it says a comma separates an address range, but there's 3 commas.
The first 'address' /^password: / has a trailing s; in the docs s is only mentioned as the replace command like s/pattern/replacement/. Not the case here.
The ^password: "(.*)"$ part looks like the Regex for isolating secret, but it's not delimited.
I can understand the end part where the back-reference \1 is printed out, but again, what are the commas doing there??
Note that I'm not interested in an easier alternative to this sed example. This will only be part of a larger bash script which will include some more sed parsing in an .htaccess file, so I'd really like to learn the syntax even if it is obscure.
Thanks for your help!
Here is sed command:
sed -En '/^password: / s,^password: "(.*)"$,\1,p'
Commas are used as regex delimiter it can very well be another delimiter like #:
sed -En '/^password: / s#^password: "(.*)"$#\1#p'`
/^password: / finds an input line that starts with password:
s#^password: "(.*)"$#\1#p finds and captures double-quoted string after password: and replaces the entire line with the captured string \1 ( so all that remains is the password )
First, the command extracts passwords from a file (or stream) and prints them to stdout.
While you "normally" might execute a sed command on all lines of a file, sed offers to specify a regex pattern which describes which lines the following command should get applied to.
In your case
/^password: /
is a regex, saying that the command:
s,^password: "(.*)"$,\1,p
should get executed for all lines looking like password: "secret". The command substitutes those lines with the password itself while suppressing the outer lines.
The substitute command might look uncommon but you can choose the delimiter in an sed command, it is not limited to /. In this case , was chosen.