I've used awk in the past for large file manipulation and substitutions.Recently, I've used it to substitute, for ex letter A with a set of characters:

$ awk '{gsub(/A/,"@@@")}1' in.txt >> out.txt

where in.txt contains strings of letters of various length. (AAA, BBB, CCC, ABABAB etc)

Later edit: I am using a WSL version of Ubuntu. Also, I have considered sed, but it does not work that well with large text files.

How can I use gsub to replace all characters A in my file with @@@, B with ###, C with %%% etc

I am guessing it should be something close to:

$ awk '{gsub(/A|B|C/,"&123")}1' in.txt > out.txt

Many thanks!

Later edit: I am using a WSL version of Ubuntu on Win10. Also, I have considered using sed, but it does not work so well with large files.

  • To start with, which version of Linux have you installed (Ubuntu server, Ubuntu desktop, Kubuntu, Lubuntu, Xubuntu, Ubuntu MATE, et al.) , and which release number? Different releases have different tools for us to recommend. Please click edit and add that vital information to your question so all the facts we need are in the question. Please don't use Add Comment, since that's our channel to you. All facts about your system should go in the Question with edit
    – K7AAY
    Apr 17 '20 at 16:31
  • This would probably be simpler in perl - whose s/patt/repl/g supports an e flag for executing code. You could use that to do a hash-based lookup on the repl side. Apr 17 '20 at 17:00

As far as I know, awk's gsub can't do anything more that simple textual replacement. You could however use repeated applications of the match function to implement a hash-based lookup with substring replacement - something like:

awk '
  BEGIN{c["A"]="@@@"; c["B"]="###"; c["C"]="%%%"} 
    while(match($0,/[A-C]/)) {
      $0 = substr($0,1,RSTART-1) c[substr($0,RSTART,1)] substr($0,RSTART+1,length($0)-RSTART)
' in.txt

In contrast, perl's s/patt/repl/g (roughly equivalent of awk's gsub) has an optional e flag that allows execution of code on the RHS. So you could do something like

perl -pe 'BEGIN{%c = (A => "@@@", B => "###", C => "%%%")} $_ =~ s/[A-C]/$c{$&}/ge' in.txt

which is likely much closer to what you had in mind.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.