I have been searching around for over an hour and I am not quite finding what I am looking for. I am trying to perform a grep match to make sure the syntax in a command is correct before proceeding.
Contents of file:
deploy type:apptype1 artifact:coolio version:1.1.1 in dev
What I am looking for is to allow multiple types, artifact, version and allow for only dev or qa. Any other text added or missing should fail.
What I have tried so far is:
grep -ie "deploy type:apptype1\|apptype2\|apptype3 artifact:.*version:.*in dev\|qa file
The problem is if I add additional text or even change "in" to "on" it still matches. I suspect it is only matching the first part and not the entire line like I am wanting?
Use GNU grep:
grep -P '^deploy type:(apptype1|apptype2|apptype3) artifact:.*version:.*in (dev|qa)$' in_file
Example:
cat > in_file <<EOF
deploy type:apptype1 artifact:coolio version:1.1.1 in dev
deploy type:apptype2 artifact:coolio version:1.1.1 in qa
deploy type:apptype1 artifact:coolio version:1.1.1 on dev
EOF
grep -P '^deploy type:(apptype1|apptype2|apptype3) artifact:.*version:.*in (dev|qa)$' in_file
Output:
deploy type:apptype1 artifact:coolio version:1.1.1 in dev
deploy type:apptype2 artifact:coolio version:1.1.1 in qa
Here, GNU grep uses option:
-P : Use Perl regexes.
^ : Beginning of the line.
$ : End of the line.
SEE ALSO:
perlre - Perl regular expressions
This works for me :
echo "deploy type:apptype2 artifact:coolio version:1.1.1 in dev" | grep -i -E "deploy type:(apptype1|apptype2|apptype3) artifact:.*version:.*in (dev|qa)"
Note the > color on the next line indicating previous command returned 0 (Green) or else non zero (Red)
Based on your example, here is a solution for BSD/GNU grep:
grep -ie "deploy type:apptype[123] artifact:[[:alnum:]].* version:[[:alnum:]].* in [(dev\|qa)]" file
Edit
#timur-shtatland's answer is better - my answer will not exclude "dev_test" or "qa_temp"
Related
For integration tests, I have output that contains full file paths. I want to have my test script replace the user-specific start of the file path (e.g. /Users/uli/) with a generic word (USER_DIR) so that I can compare the files.
The problem, of course, are the slashes in the path. I tried the solutions given here and here, but they don't work for me:
#!/bin/bash
old_path="/Users/uli/"
new_path="USERDIR"
sed -i "s#$old_path#$new_path#g" /Users/uli/Desktop/replacetarget.txt
I get the error
sed: 1: "/Users/uli/Desktop/repl ...": invalid command code u
This is the version of sed that comes with macOS 10.14.6 (it has no --version option and is installed in /usr/bin/, so no idea what exact version).
Update:
I also tried
#!/bin/bash
old_path="/Users/uli/"
old_path=${old_path//\//\\\/}
new_path="USERDIR"
regex="s/$old_path/$new_path/g"
echo $old_path
echo $regex
sed -i $regex /Users/uli/Desktop/replacetarget.txt
But I get the same error. What am I doing wrong?
BSD sed requires an argument following -i (the empty string '' indicates no backup, similar to argumentless -i in GNU sed). As a result, your script is being treated as the backup-file extention, and your input file as the script.
old_path="/Users/uli/"
new_path="USERDIR"
sed -i '' "s#$old_path#$new_path#g" /Users/uli/Desktop/replacetarget.txt
However, sed is a stream editor, based on the file editor ed, so using -i is an indication you are using the wrong tool to begin with. Just use ed.
old_path="/Users/uli/"
new_path="USERDIR"
printf 's#%s#%s#g\nwq\n' "$old_path" "$new_path" | ed /Users/uli/Desktop/replacetarget.txt
Obligatory warning: neither editor is parameterized as such; you are simpling generating the script dynamically, which means it's your responsibility to ensure that the resulting script is valid. (For example, if either parameter contains a ;, it had better be escaped to prevent (s)ed from seeing it as a command separator.)
This question already has an answer here:
Sed doesn't work in command line however regular expression in online test regex101 works
(1 answer)
Closed 4 years ago.
What I'm trying to do
Bash script to replace the uncommented php_version: "7.2" with the a user-entered version:
#!/bin/bash
# Ask desired PHP version
read -p "What version of PHP should be used? (5.6, 7.0, 7.1, or 7.2): " phpVersion
# Replace default php version with desired php version
sed -i "s/^php_version: \"[0-9]+\.[0-9]+\"/php_version: \"${phpVersion}\"/g" fileToSearchReplace.txt
Contents of fileToSearchReplace.txt which vim reports is a unix file:
APIVersion: v1.0.0
name: alpha-local
type: typo3
docroot: public
# php_version: "7.1" # PHP version to use, "5.6", "7.0", "7.1", "7.2"
php_version: "7.2"
router_http_port: "80"
router_https_port: "443"
xdebug_enabled: false
additional_hostnames: []
additional_fqdns: []
provider: default
Diagnostics
This worked: I checked the RegEx here using ^php_version: "[0-9]+\.[0-9]+" for search and php_version: "7.0" for replace (you can find replace and paste in the text a tab below. Notice I could only get the search to work using the /gm at the end. I have no idea how to get multiline to work in sed???
Environment
Windows 10 Pro host
Using MINGW64 git bash terminal
These files are part of a Docker container
I tried running this sed both in my MINGW64 git bash terminal and also inside the Ubuntu container
You cannot use + with sed by default. Either do your own + like that:
sed -i "s/^php_version: \"[0-9][0-9]*\.[0-9][0-9]*\"/php_version: \"${phpVersion}\"/g" fileToSearchReplace.txt
Or use the extended regex option -r:
sed -r -i "s/^php_version: \"[0-9]+\.[0-9]+\"/php_version: \"${phpVersion}\"/g" fileToSearchReplace.txt
Example: https://repl.it/repls/PowderblueFoolishEquipment
I don't think its a good idea to try out a regex from a site which doesn't say which class of regex it is supporting and re-using the same in your command.
You have a classic case of mix-up in which the regex pattern from the site, is of the Extended Regular Expressions and the one in your sed uses Basic Regular expression construct which does not support your [0-9]+ expression. Simply enable the ERE support with the -E switch in your sed
sed -Ei "s/^php_version: \"[0-9]+\.[0-9]+\"/php_version: \"${phpVersion}\"/g" fileToSearchReplace.txt
See the [ POSIX | GNU ] variants of the same solution, with the POSIX version using the BRE and the GNU version using ERE. Do read through this useful article on POSIX Regular Expressions on how the two variants of the regular expressions work.
You may use this script with select that lets user select a version from a menu list. You can then pass selected option to a simplified sed command:
select ver in "5.6" "7.0" "7.1" "7.2"; do
sed -i "s/^\(php_version: \).\+/\1\"$ver\"/" fileToSearchReplace.txt
break
done
I need to replace a string in a file on a remote server with this:
ssh username#${TARGETSERVER} -i /path/to/ssh-key perl -p -i -e "s#\$user = \'${SDBUSER}\'\;#\$user = \'${TDBUSER}\'\;#g" ${TARGETDIR}/configuration.php
That would replace the db user on a remote server in a joomla installation, btw.
If I execute that interactively on the remote server with all the variables filled, it IS working.
If I put the above line in a bash script, I get this message and no replacement takes place:
"Substitution pattern not terminated at -e line 1."
Any clue how I can make this work? I've already tried several escapes like \\' and so forth, but I didn't succeed.
Thanks in advance.
BINGO - Got it working:
ssh -T username#${TARGETSERVER} -i /path/to/ssh-key <<EOI
perl -p -i -e "s#\$user = \'${SDBUSER}\'\;#\$user = \'${TDBUSER}\'\;#g" ${TARGETDIR}/configuration.php
exit
EOI
From there, I could add several perl commands so I wouldn't have to have the payload of sshing in each time.
I am trying to extract logs from my application within specific time-stamps. So i wrote the following script
a= echo $1 | sed 's/\//\\\//g';
b= echo $2 | sed 's/\//\\\//g';
sed -n "/$a/,/$b/p" $3;
Here $1 and $2 are the timestamps within which i want the logs and $3 is the file from where i want it.
This script works perfect if i pass a single file. But if i multiple files or a directory as parameters it does not give any output.
This is how i am executing the script
extract.sh '6/30/14 9:03' '6/30/14 9:05' abc_*/SysOut.log
Can SED work with multiple files or the issue is with UNIX with its limitation in passing files as parameters
Any suggesstion of help in this regard?
Your sed command should be
sed -n "/$a/,/$b/p" -- "${#:3}"
Note if you're not using Bash, you can shift those arguments first before running sed:
shift 2
sed -n "/$a/,/$b/p" -- "$#"
I am working on building a .sed file to start scripting the setup of multiple apache servers. I am trying to get sed to match the default webmaster email addresses in the .conf file which works great with this egrep. However when I use sed to try and so a substitute search and replace i get no errors back but it also does not do any substituting. I test this by running the same egrep command again.
egrep -o '\b[A-Za-z0-9._%-]+#[A-Za-z0-9.-]+(\.[A-Za-z]{2,4})?\b' /home/test/httpd.conf
returns
admin#your-domain.com
root#localhost
webmaster#dummy-host.example.com
The sed command I'm trying to use is
sed -i '/ServerAdmin/ s/\b[A-Za-z0-9._%-]+#[A-Za-z0-9.-]+(\.[A-Za-z]{2,4})?\b/MY_ADMIN_ADDRESS#gmail.com/g' /home/test/httpd.conf
After running I try and verify the results by running the egrep again and it returns the same 3 email address indicating nothing was replaced.
Don't assume that any two tools use the same regular expression syntax. If you're going to be doing replacements with sed, use sed to test - not egrep. It's easy to use sed as if it were a grep command: sed -ne '/pattern/p'.
sed must be told that it needs to use extended regular expressions using the -r option then making the sed command as follows.
sed -ir '/ServerAdmin/ s/\b[A-Za-z0-9._%-]+#[A-Za-z0-9.-]+(\.[A-Za-z]{2,4})?\b/MY_ADMIN_ADDRESS#gmail.com/g' /home/test/httpd.conf
Much thanks to Kent for pointing out that the address it was missing wasnt following a ServerName