简体   繁体   中英

what is the best way to interchange 2 words in a file in bash

I want to interchange 2 words from a file .

eg: In the below file I want to replace one with two and two with one

This is a test file one and two
test line again two
last line two one

I know I can achieve this with :

 sed 's/one/\n/g;s/two/one/g;s/\n/two/g' test.txt

But in the above approach I am assuming \\n is not appearing in the line . So what will be the best way to proceed ?.

There will never [0] be a newline in the pattern space, as sed reads line by line.

It's however worth noticing that \\n in the replacement part is not strictly supported with POSIX sed. In the pattern part \\n is supported.

Reference: s/pattern/replacement/

[0] You can actually have multiply lines in the pattern space by using append commands like Next and Get. But you have to be explicit, so one could argue that newlines is the best choice for swapping values.

You don't need a regEx type replacement while using sed , just use the classic temporary string swap for replacement. ( tmp=a;a=b;b=tmp; ), works on any instances of the pattern on each line, assuming for an input file like that. To make sure the the temporary random tmp does not occur in your file, create a random string and assign it to tmp variable

$ tmp="$(openssl rand -base64 32)"
$ tmp="${tmp//[^[:alnum:]]/}"

and stripping off any non-alphanumeric characters which could harm normal sed operation.

$ cat file
This is a test file two and one two one two two two
test line again one two one two
last line one two two two

The sed logic takes care of all replacements

sed "s/two/$tmp/g;s/one/two/g;s/$tmp/one/g" file
This is a test file one and two one two one one one
test line again two one two one
last line two one one one

You can do it using awk to loop over the entries in the line:

awk '{
        for (i=1;i<=NF;i++){
          printf "%s ", ($i=="one" ? "two" : $i=="two" ? "one" : $i); 
        };
        printf "\n";
      }'  file

In fact, as noted by user andlrc , this can be simplified further by

  1. Reassigning to the $i variables.
  2. Using the default operation, ie printing the current line, which can be triggered by any true value, eg 1 .

Result:

awk '{for(i=1;i<=NF;i++){ $i=($i=="one"?"two": $i=="two"?"one": $i);}; 1}'  file

sed works on a line-by line basis. You can make sed consider multiple lines by first getting multiple lines in the buffer which is considered for stream editing.

Search for sed replace '\\n', or have a look at this

You may need to lookup pattern space, advanced sed and labels.

My general go-to sed guide is on this link

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM