mirror of
https://github.com/nushell/nushell.git
synced 2025-01-22 06:08:47 +01:00
Add multiline regex flag to str replace (#9508)
# Description This change adds a new flag to the `str replace` command: `--multiline`, `-m`. This flag will automatically add the multiline regex flag `(?m)` to the beginning of the supplied regex, allowing for the `^` and `$` regex characters to match the beginnings and ends of lines, respectively. The main advantage of this addition is to make `str replace` more closely match sed's default behavior of performing matches per-line with a simple cli flag as opposed to forcing the user to add the {somewhat clunky) regex flag themselves. This could be an especially valuable addition since [`str replace` is listed as an alternative to sed in the official documentation](https://www.nushell.sh/book/coming_from_bash.html). With this change, the following two commands would be functionally equivalent: ```bash # bash printf "non-matching line\n123. one line\n124. another line\n" | sed -r 's/^[0-9]+\. //' ``` ```bash # nu "non-matching line\n123. one line\n124. another line\n" | str replace -am '^[0-9]+\. ' '' ``` both producing the following output: ``` non-matching line one line another line ``` # User-Facing Changes 1. Adds a new flag to the `str replace` command: `--multiline`, `-m`. # Tests + Formatting I have update the unit tests to test this flag. <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> I will submit a PR for all relevant documentation changes as soon as this PR is approved.
This commit is contained in:
parent
cbb9f8efe4
commit
81abb17b38
@ -15,6 +15,7 @@ struct Arguments {
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
literal_replace: bool,
|
||||
no_regex: bool,
|
||||
multiline: bool,
|
||||
}
|
||||
|
||||
impl CmdArgument for Arguments {
|
||||
@ -53,6 +54,11 @@ impl Command for SubCommand {
|
||||
"match the pattern as a substring of the input, instead of a regular expression",
|
||||
Some('s'),
|
||||
)
|
||||
.switch(
|
||||
"multiline",
|
||||
"multi-line regex mode: ^ and $ match begin/end of line; equivalent to (?m)",
|
||||
Some('m'),
|
||||
)
|
||||
.category(Category::Strings)
|
||||
}
|
||||
|
||||
@ -77,6 +83,7 @@ impl Command for SubCommand {
|
||||
let cell_paths = (!cell_paths.is_empty()).then_some(cell_paths);
|
||||
let literal_replace = call.has_flag("no-expand");
|
||||
let no_regex = call.has_flag("string");
|
||||
let multiline = call.has_flag("multiline");
|
||||
|
||||
let args = Arguments {
|
||||
all: call.has_flag("all"),
|
||||
@ -85,6 +92,7 @@ impl Command for SubCommand {
|
||||
cell_paths,
|
||||
literal_replace,
|
||||
no_regex,
|
||||
multiline,
|
||||
};
|
||||
operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
@ -148,6 +156,11 @@ impl Command for SubCommand {
|
||||
example: r#"'GHIKK-9+*' | str replace '[*[:xdigit:]+]' 'z'"#,
|
||||
result: Some(Value::test_string("GHIKK-z+*")),
|
||||
},
|
||||
Example {
|
||||
description: "Find and replace on individual lines (multiline)",
|
||||
example: r#""non-matching line\n123. one line\n124. another line\n" | str replace -am '^[0-9]+\. ' ''"#,
|
||||
result: Some(Value::test_string("non-matching line\none line\nanother line\n")),
|
||||
},
|
||||
|
||||
]
|
||||
}
|
||||
@ -163,6 +176,7 @@ fn action(
|
||||
all,
|
||||
literal_replace,
|
||||
no_regex,
|
||||
multiline,
|
||||
..
|
||||
}: &Arguments,
|
||||
head: Span,
|
||||
@ -185,7 +199,12 @@ fn action(
|
||||
}
|
||||
} else {
|
||||
// use regular expressions to replace strings
|
||||
let regex = Regex::new(find_str);
|
||||
let flags = match multiline {
|
||||
true => "(?m)",
|
||||
false => "",
|
||||
};
|
||||
let regex_string = flags.to_string() + find_str;
|
||||
let regex = Regex::new(®ex_string);
|
||||
|
||||
match regex {
|
||||
Ok(re) => {
|
||||
@ -264,6 +283,7 @@ mod tests {
|
||||
literal_replace: false,
|
||||
all: false,
|
||||
no_regex: false,
|
||||
multiline: false,
|
||||
};
|
||||
|
||||
let actual = action(&word, &options, Span::test_data());
|
||||
|
Loading…
Reference in New Issue
Block a user