Change known words 1 and 3 of a string whilst keeping unknown word 2 constant
I have a text file and I'm trying to find all instances of Word1 Word2 Word3
in a text file and replace it with Word4 Word2 Word5
. Word2 is unknown string but the rest of the words are known.
Here is what I have tried so far
I have a string (...) foobarfoo (...)
and I want to replace it with (...) hatbarcar (...)
sed -i 's/foo.*foo/hat.*car/g' data.txt
but the result I get is
(...) hat.*car (...)
So the wildcard is finding the word string I want but I then want to use this same wildcard to write the string which replaces the old one.
Is this possible/anyone have any suggestions?
sed wildcards string
add a comment |
I have a text file and I'm trying to find all instances of Word1 Word2 Word3
in a text file and replace it with Word4 Word2 Word5
. Word2 is unknown string but the rest of the words are known.
Here is what I have tried so far
I have a string (...) foobarfoo (...)
and I want to replace it with (...) hatbarcar (...)
sed -i 's/foo.*foo/hat.*car/g' data.txt
but the result I get is
(...) hat.*car (...)
So the wildcard is finding the word string I want but I then want to use this same wildcard to write the string which replaces the old one.
Is this possible/anyone have any suggestions?
sed wildcards string
add a comment |
I have a text file and I'm trying to find all instances of Word1 Word2 Word3
in a text file and replace it with Word4 Word2 Word5
. Word2 is unknown string but the rest of the words are known.
Here is what I have tried so far
I have a string (...) foobarfoo (...)
and I want to replace it with (...) hatbarcar (...)
sed -i 's/foo.*foo/hat.*car/g' data.txt
but the result I get is
(...) hat.*car (...)
So the wildcard is finding the word string I want but I then want to use this same wildcard to write the string which replaces the old one.
Is this possible/anyone have any suggestions?
sed wildcards string
I have a text file and I'm trying to find all instances of Word1 Word2 Word3
in a text file and replace it with Word4 Word2 Word5
. Word2 is unknown string but the rest of the words are known.
Here is what I have tried so far
I have a string (...) foobarfoo (...)
and I want to replace it with (...) hatbarcar (...)
sed -i 's/foo.*foo/hat.*car/g' data.txt
but the result I get is
(...) hat.*car (...)
So the wildcard is finding the word string I want but I then want to use this same wildcard to write the string which replaces the old one.
Is this possible/anyone have any suggestions?
sed wildcards string
sed wildcards string
edited Dec 16 at 11:49
Rui F Ribeiro
38.9k1479129
38.9k1479129
asked Sep 12 '17 at 9:01
JHS
31
31
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
The problem with a
sed -i 's/foo(.*)foo/hat1car/g'
approach is that it would change fooxfoo fooyfoo
to hatxfoo fooycar
as that .*
is greedy.
You can use perl
instead with its non-greedy .*?
operator.
perl -i -pe 's/foo(.*?)foo/hat$1car/g'
(which also has the advantage of being more portable. That -i
comes from perl
and is not available in many sed
implementations (and when it is, is not interpreted the same by all)).
With GNU sed
, and provided $POSIXLY_CORRECT
is not in the environment, you could do:
sed -i 's/foo/n/g;s/n([^n]*)n/hat1car/g;s/n/foo/g'
That is, replace foo
with a character (n
, the line delimiter) that cannot occur in the line so we can use [^n]*
to achieve the non-greedy equivalent.
If POSIXLY_CORRECT is in the environment, then [^n]
would match any character but and
n
as POSIX requires instead of any character but newline. You can always do:
(unset -v POSIXLY_CORRECT; exec sed...)
if you want your script to still work in environments where POSIXLY_CORRECT is set.
add a comment |
The replacement string in s/PATTERN/REPLACEMENT/
is not a regular expression.
You will be able to capture what is matched by a bit of the pattern and use it in the replacement if you wish:
sed -r 's/foo(.*)foo/hat1car/g' file
This will capture anything between two occurrences of foo
on the same line, and insert that bit between hat
and car
. The 1
says "insert anything that was captured by the first parentheses".
Note that .*
is "greedy" so if you have foobarfoofoobarfoo
, 1
will be barfoofoobar
, not bar
.
add a comment |
With sed, you can use (
and )
to make a capture group which can be referenced as 1
in the replacement part of the substitution:
sed 's/foo(.*)foo/hat1car/g'
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f391758%2fchange-known-words-1-and-3-of-a-string-whilst-keeping-unknown-word-2-constant%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
The problem with a
sed -i 's/foo(.*)foo/hat1car/g'
approach is that it would change fooxfoo fooyfoo
to hatxfoo fooycar
as that .*
is greedy.
You can use perl
instead with its non-greedy .*?
operator.
perl -i -pe 's/foo(.*?)foo/hat$1car/g'
(which also has the advantage of being more portable. That -i
comes from perl
and is not available in many sed
implementations (and when it is, is not interpreted the same by all)).
With GNU sed
, and provided $POSIXLY_CORRECT
is not in the environment, you could do:
sed -i 's/foo/n/g;s/n([^n]*)n/hat1car/g;s/n/foo/g'
That is, replace foo
with a character (n
, the line delimiter) that cannot occur in the line so we can use [^n]*
to achieve the non-greedy equivalent.
If POSIXLY_CORRECT is in the environment, then [^n]
would match any character but and
n
as POSIX requires instead of any character but newline. You can always do:
(unset -v POSIXLY_CORRECT; exec sed...)
if you want your script to still work in environments where POSIXLY_CORRECT is set.
add a comment |
The problem with a
sed -i 's/foo(.*)foo/hat1car/g'
approach is that it would change fooxfoo fooyfoo
to hatxfoo fooycar
as that .*
is greedy.
You can use perl
instead with its non-greedy .*?
operator.
perl -i -pe 's/foo(.*?)foo/hat$1car/g'
(which also has the advantage of being more portable. That -i
comes from perl
and is not available in many sed
implementations (and when it is, is not interpreted the same by all)).
With GNU sed
, and provided $POSIXLY_CORRECT
is not in the environment, you could do:
sed -i 's/foo/n/g;s/n([^n]*)n/hat1car/g;s/n/foo/g'
That is, replace foo
with a character (n
, the line delimiter) that cannot occur in the line so we can use [^n]*
to achieve the non-greedy equivalent.
If POSIXLY_CORRECT is in the environment, then [^n]
would match any character but and
n
as POSIX requires instead of any character but newline. You can always do:
(unset -v POSIXLY_CORRECT; exec sed...)
if you want your script to still work in environments where POSIXLY_CORRECT is set.
add a comment |
The problem with a
sed -i 's/foo(.*)foo/hat1car/g'
approach is that it would change fooxfoo fooyfoo
to hatxfoo fooycar
as that .*
is greedy.
You can use perl
instead with its non-greedy .*?
operator.
perl -i -pe 's/foo(.*?)foo/hat$1car/g'
(which also has the advantage of being more portable. That -i
comes from perl
and is not available in many sed
implementations (and when it is, is not interpreted the same by all)).
With GNU sed
, and provided $POSIXLY_CORRECT
is not in the environment, you could do:
sed -i 's/foo/n/g;s/n([^n]*)n/hat1car/g;s/n/foo/g'
That is, replace foo
with a character (n
, the line delimiter) that cannot occur in the line so we can use [^n]*
to achieve the non-greedy equivalent.
If POSIXLY_CORRECT is in the environment, then [^n]
would match any character but and
n
as POSIX requires instead of any character but newline. You can always do:
(unset -v POSIXLY_CORRECT; exec sed...)
if you want your script to still work in environments where POSIXLY_CORRECT is set.
The problem with a
sed -i 's/foo(.*)foo/hat1car/g'
approach is that it would change fooxfoo fooyfoo
to hatxfoo fooycar
as that .*
is greedy.
You can use perl
instead with its non-greedy .*?
operator.
perl -i -pe 's/foo(.*?)foo/hat$1car/g'
(which also has the advantage of being more portable. That -i
comes from perl
and is not available in many sed
implementations (and when it is, is not interpreted the same by all)).
With GNU sed
, and provided $POSIXLY_CORRECT
is not in the environment, you could do:
sed -i 's/foo/n/g;s/n([^n]*)n/hat1car/g;s/n/foo/g'
That is, replace foo
with a character (n
, the line delimiter) that cannot occur in the line so we can use [^n]*
to achieve the non-greedy equivalent.
If POSIXLY_CORRECT is in the environment, then [^n]
would match any character but and
n
as POSIX requires instead of any character but newline. You can always do:
(unset -v POSIXLY_CORRECT; exec sed...)
if you want your script to still work in environments where POSIXLY_CORRECT is set.
edited Sep 12 '17 at 9:33
answered Sep 12 '17 at 9:22
Stéphane Chazelas
299k54563913
299k54563913
add a comment |
add a comment |
The replacement string in s/PATTERN/REPLACEMENT/
is not a regular expression.
You will be able to capture what is matched by a bit of the pattern and use it in the replacement if you wish:
sed -r 's/foo(.*)foo/hat1car/g' file
This will capture anything between two occurrences of foo
on the same line, and insert that bit between hat
and car
. The 1
says "insert anything that was captured by the first parentheses".
Note that .*
is "greedy" so if you have foobarfoofoobarfoo
, 1
will be barfoofoobar
, not bar
.
add a comment |
The replacement string in s/PATTERN/REPLACEMENT/
is not a regular expression.
You will be able to capture what is matched by a bit of the pattern and use it in the replacement if you wish:
sed -r 's/foo(.*)foo/hat1car/g' file
This will capture anything between two occurrences of foo
on the same line, and insert that bit between hat
and car
. The 1
says "insert anything that was captured by the first parentheses".
Note that .*
is "greedy" so if you have foobarfoofoobarfoo
, 1
will be barfoofoobar
, not bar
.
add a comment |
The replacement string in s/PATTERN/REPLACEMENT/
is not a regular expression.
You will be able to capture what is matched by a bit of the pattern and use it in the replacement if you wish:
sed -r 's/foo(.*)foo/hat1car/g' file
This will capture anything between two occurrences of foo
on the same line, and insert that bit between hat
and car
. The 1
says "insert anything that was captured by the first parentheses".
Note that .*
is "greedy" so if you have foobarfoofoobarfoo
, 1
will be barfoofoobar
, not bar
.
The replacement string in s/PATTERN/REPLACEMENT/
is not a regular expression.
You will be able to capture what is matched by a bit of the pattern and use it in the replacement if you wish:
sed -r 's/foo(.*)foo/hat1car/g' file
This will capture anything between two occurrences of foo
on the same line, and insert that bit between hat
and car
. The 1
says "insert anything that was captured by the first parentheses".
Note that .*
is "greedy" so if you have foobarfoofoobarfoo
, 1
will be barfoofoobar
, not bar
.
edited Sep 12 '17 at 10:12
Stéphane Chazelas
299k54563913
299k54563913
answered Sep 12 '17 at 9:23
Kusalananda
121k16229372
121k16229372
add a comment |
add a comment |
With sed, you can use (
and )
to make a capture group which can be referenced as 1
in the replacement part of the substitution:
sed 's/foo(.*)foo/hat1car/g'
add a comment |
With sed, you can use (
and )
to make a capture group which can be referenced as 1
in the replacement part of the substitution:
sed 's/foo(.*)foo/hat1car/g'
add a comment |
With sed, you can use (
and )
to make a capture group which can be referenced as 1
in the replacement part of the substitution:
sed 's/foo(.*)foo/hat1car/g'
With sed, you can use (
and )
to make a capture group which can be referenced as 1
in the replacement part of the substitution:
sed 's/foo(.*)foo/hat1car/g'
answered Sep 12 '17 at 9:17
Anthony Geoghegan
7,54543954
7,54543954
add a comment |
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f391758%2fchange-known-words-1-and-3-of-a-string-whilst-keeping-unknown-word-2-constant%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown