Skip to content

Commit 5da5b54

Browse files
committed
Enhance exact text replacement functionality in line_in_file
- Updated documentation to clarify that the `exact` action treats special characters (dots, brackets, parentheses, etc.) as literal characters, ensuring true literal matching. - Added new functions `escape_sed_pattern` and `escape_sed_replacement` to properly escape special characters for use in sed, improving the reliability of text replacements in configuration files.
1 parent 67e419a commit 5da5b54

2 files changed

Lines changed: 32 additions & 2 deletions

File tree

docs/content/docs/8.advanced/99.create-your-own-template.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ line_in_file [--file FILE] [--action ACTION] [ARGUMENTS...]
129129
| `ensure` | Ensures specified lines exist in the file. | One or more lines to ensure. | Appends the line(s) to the end of the file. |
130130
| `replace` | Replaces a line containing specific content with a new line. | Two arguments: search content and replacement line. | Appends the replacement line to the file. |
131131
| `after` | Inserts a new line after a line containing specific content. | Two arguments: search content and line to insert. | Appends both the search content and new line to the file. |
132-
| `exact` | Performs an exact replacement of text within the file. | Two arguments: exact text to replace and replacement text. | Returns an error. |
132+
| `exact` | Performs an exact replacement of text within the file. Special characters (dots, brackets, parentheses, etc.) are treated as literal characters. | Two arguments: exact text to replace and replacement text. | Returns an error. |
133133
| `search` | Searches for specified content in the file. | One argument: content to search for. | Returns false (exit code 1). |
134134
| `delete` | Deletes lines containing specified content. | One argument: content to delete. | Returns an error if the content is not found. |
135135

@@ -169,6 +169,18 @@ label: Perform an exact text replacement
169169
line_in_file --file document.txt --action exact "old text" "new text"
170170
```
171171
::
172+
173+
::code-panel
174+
---
175+
label: Replace text with special characters (dots, parentheses, etc.)
176+
---
177+
```bash
178+
# Works perfectly with special regex characters
179+
line_in_file --file docker-compose.yml --action exact \
180+
"traefik.http.services.app.loadbalancer.server.port=8443" \
181+
"traefik.http.services.app.loadbalancer.server.port=8080"
182+
```
183+
::
172184
::code-panel
173185
---
174186
label: Operate on multiple files
@@ -191,6 +203,7 @@ The function will output error messages to stderr and return a non-zero exit cod
191203

192204
- The function uses `sed_inplace` for in-place file modifications. Ensure this function is available in your environment.
193205
- When using the `replace` action, forward slashes in the replacement string are automatically escaped.
206+
- When using the `exact` action, all regex special characters (dots, brackets, parentheses, etc.) are automatically escaped, ensuring true literal matching. This makes it perfect for replacing configuration values, URLs, or any text containing special characters.
194207
- The function creates the target file if it doesn't exist.
195208

196209
## Testing your template

lib/functions.sh

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,18 @@ last_pull_timestamp() {
702702
grep "^$escaped_project_dir " "$cache_file" | awk '{print $2}'
703703
}
704704

705+
escape_sed_pattern() {
706+
# Escape special characters for use in sed search patterns
707+
# This ensures exact string matching by escaping regex metacharacters
708+
printf '%s' "$1" | sed 's/[][\.|$(){}?+*^/]/\\&/g'
709+
}
710+
711+
escape_sed_replacement() {
712+
# Escape special characters for use in sed replacement strings
713+
# In replacement strings, we need to escape: \ / &
714+
printf '%s' "$1" | sed 's/[\/&]/\\&/g' | sed 's/\\/\\\\/g'
715+
}
716+
705717
line_in_file() {
706718
local action="ensure"
707719
local files=()
@@ -793,7 +805,12 @@ ${args[1]}" "$file"
793805
return 1
794806
fi
795807
if grep -qF -- "${args[0]}" "$file"; then
796-
sed_inplace "s/${args[0]}/${args[1]}/g" "$file"
808+
# Escape special regex characters for exact matching
809+
local escaped_search
810+
local escaped_replace
811+
escaped_search=$(escape_sed_pattern "${args[0]}")
812+
escaped_replace=$(escape_sed_replacement "${args[1]}")
813+
sed_inplace "s/${escaped_search}/${escaped_replace}/g" "$file"
797814
else
798815
if [[ "$ignore_missing" == true ]]; then
799816
return 0

0 commit comments

Comments
 (0)