Shell - check if file contains string with newlines inside [duplicate] - shell

This question already has answers here:
How can I search for a multiline pattern in a file?
(11 answers)
Closed 5 years ago.
I've declared a string with two newlines inside of string
somestring=$'\n##### Branch FREEZE enable/disable\nRelease:'
I have a $file with a text inside like this
###############################
##### Branch RELEASE enable/disable
Release: disable
##### Branch FREEZE enable/disable
Freeze: disable
##### Mail list #####
I am trying to figure out, if there is a string inside with both of the newlines with a command
if grep -q "$somestring" "$file"; then
echo "found the string"
But the result is always positive, when there is a newline inside of string.
How can I make it work correct with newlines inside?

grep patterns are matched against individual lines so there is no way for a pattern to match a newline found in the input.
try pcregrep instead of regular grep:
pcregrep -M "pattern1.*\n.*pattern2" filename
the -M option allows it to match across multiple lines, so you can search for newlines as \n.

Related

Replace string containing slash using SED command [duplicate]

This question already has answers here:
How to insert strings containing slashes with sed? [duplicate]
(11 answers)
Closed 3 years ago.
I am trying the below code to replace the string /IRM/I with E/IRM/I but am getting the file processed with no error and no transformation. I assume I'm using the cancel character incorrectly to allow the forward slash. Any help is much appreciated.
sed -i '/\/IRM\/IE\/IRM\/I/g'
A sed command needs to specify an operation (like s to replace), and that operation requires a sigil. You don't need to use a slash as that sigil.
printf '%s\n' 'This is a test: </IRM/I>' | \
sed -e 's#/IRM/I#E/IRM/I#g'
...correctly emits as output:
This is a test: <E/IRM/I>
Note that we added a s at the beginning of your sed expression, and followed it up with a # -- a sigil that isn't contained anywhere in the source or replacement strings, so you don't need to escape it as you would /.

replace all special characters with a backslash plus special character in Unix Shell [duplicate]

This question already has answers here:
Replacing some characters in a string with another character
(6 answers)
Closed 3 years ago.
I need to replace the special character which is not alphanumeric with a backslash in a string.
How do i do it in Bash? My version is 4.1
I can capture the special character the plus symbol using the following regex
([^[:alnum:]])
For example, applied to the string
Alan5+6imson
I can do
$ echo $orig_str |sed 's/([^[:alnum:]])/\\1/g'
Alan5+6imson
I need the output as
Alan5\+6imson
How can I replace it in Bash?
I tried the above regex but not sure how to perform a replacement.
Do i need to use some other tool or something like sed?
Would you please try:
echo "$orig_str" | sed 's/\([^[:alnum:]]\)/\\\1/g'
or:
echo "$orig_str" | sed 's/[^[:alnum:]]/\\&/g'

Escaping forward slashes in sed command [duplicate]

This question already has answers here:
Escape a string for a sed replace pattern
(17 answers)
sed search and replace strings containing / [duplicate]
(2 answers)
Closed 3 years ago.
With Bash and SED I'm trying to replace two strings in a js file with URL's.
The two urls that should be inserted is input params when I run the .sh script.
./deploy.sh https://hostname.com/a/index.html https://hostname2.com/test
However to make this usable in my sed command I have to escape all forward slashes with: \\ ?
./deploy.sh https:\\/\\/hostname.com\\/a\\/index.html https:\\/\\/hostname2.com\\/test
If they are escaped this SED command works on Mac OSX Sierra
APP_URL=$1
API_URL=$2
sed "s/tempAppUrl/$APP_URL/g;s/tempApiUrl/$API_URL/g" index.src.js > index.js
Now I don't want to insert escaped urls as params, I want the script it self to escape the forward slashes.
This is what I've tried:
APP_URL=$1
API_URL=$2
ESC_APP_URL=(${APP_URL//\//'\\/'})
ESC_API_URL=(${API_URL//\//'\\/'})
echo 'Escaped URLS'
echo $ESC_APP_URL
#Echos result: https:\\/\\/hostname.com\\/a\\/index.html
echo $ESC_API_URL
#Echos result: https:\\/\\/hostname2.com\\/test
echo "Inserting app-URL and api-URL before dist"
sed "s/tempAppUrl/$ESC_APP_URL/g;s/tempApiUrl/$ESC_API_URL/g" index.src.js > index.js
The params looks the same but in this case the SED throws a error
sed: 1: "s/tempAppUrl/https:\\/\ ...": bad flag in substitute command: '\'
Could anyone tell me the difference here? The Strings looks the same but gives different results.
I suggest to replace
sed "s/regex/replace/" file
with
sed "s|regex|replace|" file
if your sed supports it. Then it is no longer necessary to escape the slashes.
The character directly after the s determines which character is the separator, which must appear three times in the s command.

Bash concatenating lines in a variable [duplicate]

This question already has an answer here:
Variable expansion is different in zsh from that in bash
(1 answer)
Closed 7 years ago.
I was trying to convert my zsh prompt to bash and I had this line:
local gitstat=$(git status 2>/dev/null | grep '^\(Untracked\|Changes\|Changed but not updated:\)')
In zsh, when in a Git repository with unstaged changes and untracked files, the variable $gitstat is set to
Changes not staged for commit:
Untracked files:
but in bash, it is set to
Changes not staged for commit: Untracked files:
It seems that bash is concatenating the lines together when run in a subshell and assigning to a variable, and I can't find any explanation why or how to stop this.
bash isn't concatenating the lines; rather, you are not quoting the expansion of $gitstatus before printing it. If you write
echo $gitstatus
bash first expands $gitstatus, then performs word-splitting on the resulting string. Any whitespace, including embedded newlines, are treated as word separators, so that the string is split into multiple words, each of which is passed to echo as a separate argument. echo then displays each argument on one line, separated by a single space.
In contrast, quoting the expansion
echo "$gitstatus"
prevents the argument from being split into words, and the entire string (embedded newlines and all) are passed to echo as a single argument.
The difference between bash and zsh in this case is that zsh, in contrast to the POSIX specification, does not perform word-splitting on unquoted parameter expansions.

Bash loop - tokenize on lines rather than words [duplicate]

This question already has answers here:
Bash and filenames with spaces
(6 answers)
Closed 8 years ago.
I'm writing a script to do variable substitution into a Java properties file, of the format name=value. I have a source file, source.env like this:
TEST_ENV_1=test environment variable one
TEST_ENV_2=http://test.environment.com/one
#this is a comment with an equal sign=blah
TEST_ENV_3=/var/log/test/env/2.log
My script will replace every occurence of TEST_ENV_1 in the file dest.env with "test environment variable one", and so on.
I'm trying to process a line at a time, and having problems because looping on output from a command like sed or grep tokenizes on white space rather than the entire line:
$ for i in `sed '/^ *#/d;s/#.*//' source.env`; do
echo $i
done
TEST_ENV_1=test
environment
variable
one
TEST_ENV_2=http://test.environment.com/one
TEST_ENV_3=/var/log/test/env/2.log
How do I treat them as lines? What I want to be able to do is split each line apart on the "=" sign and make a sed script with a bunch of substitution regex's based on the source.env file.
sed '/^ *#/d;s/#.*//' source.env | while read LINE; do
echo "$LINE"
done
An alternative is to change $IFS as per #Jim's answer. It's better to avoid backticks in this case as they'll cause the entire file to be read in at once, whereas piping the output of sed to while above will allow the file to be processed line by line without reading the whole thing in to memory.

Resources