Change known words 1 and 3 of a string whilst keeping unknown word 2 constant












0














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?










share|improve this question





























    0














    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?










    share|improve this question



























      0












      0








      0







      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?










      share|improve this question















      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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Dec 16 at 11:49









      Rui F Ribeiro

      38.9k1479129




      38.9k1479129










      asked Sep 12 '17 at 9:01









      JHS

      31




      31






















          3 Answers
          3






          active

          oldest

          votes


















          2














          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.






          share|improve this answer































            1














            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.






            share|improve this answer































              -1














              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'





              share|improve this answer





















                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
                });


                }
                });














                draft saved

                draft discarded


















                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









                2














                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.






                share|improve this answer




























                  2














                  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.






                  share|improve this answer


























                    2












                    2








                    2






                    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.






                    share|improve this answer














                    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.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Sep 12 '17 at 9:33

























                    answered Sep 12 '17 at 9:22









                    Stéphane Chazelas

                    299k54563913




                    299k54563913

























                        1














                        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.






                        share|improve this answer




























                          1














                          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.






                          share|improve this answer


























                            1












                            1








                            1






                            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.






                            share|improve this answer














                            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.







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Sep 12 '17 at 10:12









                            Stéphane Chazelas

                            299k54563913




                            299k54563913










                            answered Sep 12 '17 at 9:23









                            Kusalananda

                            121k16229372




                            121k16229372























                                -1














                                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'





                                share|improve this answer


























                                  -1














                                  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'





                                  share|improve this answer
























                                    -1












                                    -1








                                    -1






                                    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'





                                    share|improve this answer












                                    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'






                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered Sep 12 '17 at 9:17









                                    Anthony Geoghegan

                                    7,54543954




                                    7,54543954






























                                        draft saved

                                        draft discarded




















































                                        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.




                                        draft saved


                                        draft discarded














                                        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





















































                                        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







                                        Popular posts from this blog

                                        Morgemoulin

                                        Scott Moir

                                        Souastre