Dears,
I need your support with this below regex I’ve been at it for the last 5 hours and could not figure it out
define(s*['"]DB_HOST['"]s*,s*['"]([^'"]+)['"])
The task I have is simple I need a regex to extract WordPress database information and I will be using it in an Ansible playbook
/** The host of the database for WordPress */
define( 'DB_HOST', 'database_host_here' );
the above is the format
I tried more than regex with the help of ChatGPT and other GenAI tools but every output fails due to a regex escape issue
this is my current playbook
---
- name: Update wp-config.php with new template
hosts: localhost
vars_prompt:
- name: username
prompt: "Enter the username"
private: false
vars:
wp_config_filename: "wp-config.php"
enable_debug: false
multi_site: false
search_paths:
- "/home/{{ username }}/public_html/public"
tasks:
- name: Find wp-config.php files
ansible.builtin.find:
paths: "{{ search_paths }}"
patterns: "{{ wp_config_filename }}"
register: wp_config_files
- name: Fail if no wp-config.php files found
ansible.builtin.fail:
msg: "No wp-config.php files found in the provided paths."
when: wp_config_files.matched == 0
- name: Debug wp-config.php files
ansible.builtin.debug:
var: wp_config_files
- name: Read existing wp-config.php for database credentials
ansible.builtin.slurp:
src: "{{ item.path }}"
loop: "{{ wp_config_files.files }}"
loop_control:
loop_var: item
register: wp_config_content
when: wp_config_files.matched > 0
- name: Decode base64 encoded wp-config.php content
ansible.builtin.set_fact:
wp_config_decoded: "{{ wp_config_content.results | map(attribute='content') | map('b64decode') | list }}"
- name: Debug decoded wp-config.php content
ansible.builtin.debug:
var: wp_config_decoded
- name: Set database credentials from existing wp-config.php
ansible.builtin.set_fact:
db_host: "{{ item | regex_search('define\(\s*['"]DB_HOST['"]\s*,\s*['"]([^'"]+)['"]') | default('localhost') }}"
db_name: "{{ item | regex_search('define\(\s*['"]DB_NAME['"]\s*,\s*['"]([^'"]+)['"]') | default('wordpress') }}"
db_user: "{{ item | regex_search('define\(\s*['"]DB_USER['"]\s*,\s*['"]([^'"]+)['"]') | default('root') }}"
db_password: "{{ item | regex_search('define\(\s*['"]DB_PASSWORD['"]\s*,\s*['"]([^'"]+)['"]') | default('password') }}"
loop: "{{ wp_config_decoded }}"
loop_control:
loop_var: item
- name: Debug extracted database credentials
ansible.builtin.debug:
msg: >
DB Name: {{ db_name }},
DB User: {{ db_user }},
DB Password: {{ db_password }},
DB Host: {{ db_host }}
- name: Create a new wp-config.php from template
ansible.builtin.template:
src: "wp-config.php.j2"
dest: "{{ item.path }}"
mode: "0644"
loop: "{{ wp_config_files.files }}"
when: wp_config_files.matched > 0
I have a shared hosting environment with more than one WordPress website and I want to make all the settings are the same so I want to automate the detection of the database information, update the template, and place it in the correct path.
define(s*['"]DB_HOST['"]s*,s*['"]([^'"]+)['"])
It fails with ansible
UPDATE
Thanks to @WiktorStribiżew I was able to figure out the solution to my issue
The new and updated regex value with regex_search for ansible
regex_search('define\s*\(\s*[\x22\x27]DB_HOST[\x22\x27]\s*,\s*[\x22\x27]([^\x22\x27]+)[\x22\x27]\s*\)', '\1') | first
UPDATE 2:
Based on @U880D’s answer, if someone faces the same case or wants to implement the same task.
Full Playbook:
---
- name: Update wp-config.php with new template
hosts: all
become: true
tasks:
- name: Find all user directories under /home
ansible.builtin.find:
paths: "{{ search_path }}"
file_type: directory
register: user_dirs
- name: Find all wp-config.php files in user directories
ansible.builtin.find:
paths: "{{ item.path }}/public_html"
patterns: "wp-config.php"
register: wp_config_files
loop: "{{ user_dirs.files }}"
- name: Fail if no wp-config.php files found
ansible.builtin.fail:
msg: "No wp-config.php files found in the provided paths."
when: wp_config_files.matched == 0
- name: Debug wp-config.php files
ansible.builtin.debug:
var: wp_config_files
- name: Read existing wp-config.php for database credentials
ansible.builtin.slurp:
src: "{{ item.path }}"
loop: "{{ wp_config_files.files }}"
register: wp_config_content
when: wp_config_files.matched > 0
- name: Debug wp-config.php content
ansible.builtin.debug:
var: wp_config_content.results
- name: Set database credentials from existing wp-config.php
ansible.builtin.set_fact:
db_host: >-
{{ item.content | b64decode | regex_search('DB_HOST(.+)', '\1') | regex_search('([A-Za-z])+') }}
db_name: >-
{{ item.content | b64decode | regex_search('DB_NAME(.+)', '\1') | regex_search('([A-Za-z])+') }}
db_user: >-
{{ item.content | b64decode | regex_search('DB_USER(.+)', '\1') | regex_search('([A-Za-z])+') }}
db_password: >-
{{ item.content | b64decode | regex_search('DB_PASSWORD(.+)', '\1') | regex_search('([A-Za-z])+') }}
loop: "{{ wp_config_content.results }}"
loop_control:
loop_var: item
when: item.content is defined
- name: Debug extracted database credentials
ansible.builtin.debug:
msg: >-
DB Name: {{ db_name }},
DB User: {{ db_user }},
DB Password: {{ db_password }},
DB Host: {{ db_host }}
- name: Create a new wp-config.php from template
ansible.builtin.template:
src: "wp-config.php.j2"
dest: "{{ item.path }}"
mode: "0644"
loop: "{{ wp_config_files.files }}"
when: wp_config_files.matched > 0
fariscode is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
9
Maybe a simpler approach is feasible like shown in the minimal example
---
- hosts: localhost
become: false
gather_facts: false
vars:
wp_config_decoded: |
define( 'DB_NAME', 'test' );
/** The host of the database for WordPress */
define( 'DB_HOST', 'database_host_here' );
tasks:
- name: Given answer
debug:
msg: "{{ wp_config_decoded | regex_search('define\(\s*[\x22\x27]DB_HOST[\x22\x27]\s*,\s*[\x22\x27]([^\x22\x27]+)[\x22\x27]\s*\)', '\1') | first }}"
- name: Easier to read, maintain and operate
debug:
msg: "{{ wp_config_decoded | regex_search('DB_NAME(.+)', '\1') | regex_search('([A-Za-z])+') }}"
resulting into an output of
TASK [Given answer] ***************************
ok: [localhost] =>
msg: database_host_here
TASK [Easier to read, maintain and operate] ***
ok: [localhost] =>
msg: test
Thanks To
- Extracting part of the string using Ansible
regex_search
and save the output as a variable
1
There is a workaround for adding double and single quotes to your regex pattern if you have trouble understanding how to escape them inside your string literals. This works with most -if not all – NFA regex engines.
You can match "
with x22
and '
with x27
escape entity.
So, your pattern will look like
regex_search('define\(\s*[\x22\x27]DB_HOST[\x22\x27]\s*,\s*[\x22\x27]([^\x22\x27]+)[\x22\x27]\s*\)')
Note that if you need to get the group value from the result, you need to specify it as the second argument to regex_search
:
regex_search('define\(\s*[\x22\x27]DB_HOST[\x22\x27]\s*,\s*[\x22\x27]([^\x22\x27]+)[\x22\x27]\s*\)', '\1')
Since you obtain a list as a result of your code execution, and you only need the first item in that list, all you need is to add the | first
after your regex search command.