2

I am working on a bash script that can add nginx location blocks to a file taking in a URL. To prevent duplicates this script will also remove them if if it already exists.

For removing a block if it already exists I made the regex below. ^location\s\/${URLGOESHERE} {[\s\S]*?(?=\n{2,})$

The regex needs to match the entire multiline block like this:

location /URLGOESHERE {
  try_files $uri /URLGOESHERE/index.php?$query_string;
}

I would like the regex to match anything inside the block until the close bracket} There will be multiple blocks inside the file e.g

location /URL1HERE {
  expires 7d;
  try_files $uri /URLGOESHERE/index.php?$query_string;
  allow all;
  Etc....
}

location /URL2HERE {
  try_files $uri /URLGOESHERE/index.php?$query_string;
}
location /URL3HERE {
  try_files $uri /URLGOESHERE/index.php?$query_string;
}

location /URL4HERE {
  expires 7d;
  try_files $uri /URLGOESHERE/index.php?$query_string;
  allow all;
  Etc....
}

The regex I made works but only if there is a blank line before and after the block. So with my regex URL2, 3(No newline either before or after) and 4 (No newline at end of file) would not be found by pcregrep

I was wondering if the regex can be made to match the block exactly without needing these blank lines.

oguz ismail
  • 1
  • 16
  • 47
  • 69
azy141
  • 39
  • 3

1 Answers1

0

EDIT: Since OP has changed samples, so adding following solution now. Based on current shown samples only.

awk '/location \/URL([0-9]+)?HERE[[:space:]]+?/{found=1} found; /}/ && found{found=""}'  Input_file


With your shown samples/attempts, please try following awk code. This will give statements between { to } removing new lines from it.

awk -v RS='location[[:space:]]+/URLGOESHERE[[:space:]]+{\n*[[:space:]]+try_files[[:space:]]+\\$uri[[:space:]]+\\/[^?]*\\?\\$query_string;\n*}' '
RT{
  gsub(/.*\n*{\n*[[:space:]]+/,"",RT)
  gsub(/\n*}/,"",RT)
 print RT
}
'  Input_file

Explanation: Making field separator as per shown samples to match values to get Location block including blank lines and then in each matched separator value removing blank lines.

For example let's say we have following Input_file:

cat Input_file
location /URLGOESHERE {

  try_files $uri /URLGOESHERE/index.php?$query_string;



}

location /URLGOESHERE {
  try_files $uri /URLGOESHERE/index.php?$query_string;
}

After running above code we will get following output:

try_files $uri /URLGOESHERE/index.php?$query_string;
try_files $uri /URLGOESHERE/index.php?$query_string;

Explanation of regex used: Adding detailed explanation for above code.

location[[:space:]]+/URLGOESHERE   ##Matching location followed by spaces followed by /URLGOESHERE
[[:space:]]+{\n*                   ##Followed by spaces { and 0 or more new lines.
[[:space:]]+try_files[[:space:]]+  ##Followed by spaces try_files followed by 1 or more spaces.
\\$uri[[:space:]]+                 ##followed by $uri spaces here.
\\/[^?]*\\?\\$query_string;\n*}    ##followed by / till ? occurrence followed by $query_stirng; followed by 0 or more new lines.
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
  • Hi Ravinder many thanks for this, I appreciate the help hugely however I am not sure this is what I meant. I am looking for a regex that will match the beginning of the location block through to the end including the braces. There could be any number of lines within the block Then I can pass the URL into the regex and it will check the config file if this block exists and remove it if it's already present. – azy141 Jun 22 '21 at 16:09
  • @azy141, please edit your question with more details of input and expected output so that I could understand it more clearly, thank you. – RavinderSingh13 Jun 22 '21 at 16:13
  • I have updated the question to contain more detail :) – azy141 Jun 24 '21 at 12:46
  • @azy141, ok sure, I have added EDIT solution now, please do check it once and ley me know how it goes. – RavinderSingh13 Jun 24 '21 at 13:35