Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find and replace pattern of fileA in fileC by fileB pattern

I have two files, fileA with a list of name :

AAAAA 
BBBBB
CCCCC
DDDDD

and another fileB with another list :

111 
222
333
444

and a third fileC with some text :

Hello AAAAA toto BBBBB dear "AAAAA" trird BBBBBB tuizf AAAAA dfdsf CCCCC

So I need to find and replace every pattern of fileA in fileC by fileB pattern. It works ! But i realised that fileC contains words like "AAAAA" and it isn't replace by "111".

I'm doing this but it doesn't seems to work.

#! /bin/bash
while IFS= read -r lineA && IFS= read -r lineB <&3; do
sed -i -e "s/$lineA/$lineB/g" fileC
done <fileA 3<fileB
like image 812
Peter Dev Avatar asked Oct 15 '13 08:10

Peter Dev


People also ask

How will you replace a pattern in a file?

Find and replace text within a file using sed command Use Stream EDitor (sed) as follows: sed -i 's/old-text/new-text/g' input.txt. The s is the substitute command of sed for find and replace. It tells sed to find all occurrences of 'old-text' and replace with 'new-text' in a file named input.txt.

How do I find and replace pattern?

Given a list of strings words and a string pattern , return a list of words[i] that match pattern . You may return the answer in any order. A word matches the pattern if there exists a permutation of letters p so that after replacing every letter x in the pattern with p(x) , we get the desired word.

How do you grep and replace?

Another option would be to just use perl with globstar. Enabling shopt -s globstar in your . bashrc (or wherever) allows the ** glob pattern to match all sub-directories and files recursively. Thus using perl -pXe 's/SEARCH/REPLACE/g' -i ** will recursively replace SEARCH with REPLACE .

How do you replace a pattern in a string?

To perform multiple replacements in each element of string , pass a named vector ( c(pattern1 = replacement1) ) to str_replace_all . Alternatively, pass a function to replacement : it will be called once for each match and its return value will be used to replace the match.


Video Answer


3 Answers

This is a good job for GNU awk:

$ cat replace.awk 
FILENAME=="filea" {
    a[FNR]=$0
    next
}
FILENAME=="fileb" {
    b[a[FNR]]=$0
    next
}
{
    for (i=1;i<=NF;i++) {
        printf "%s%s",(b[$i]?b[$i]:$i),(i==NF?RS:FS)
    }
}

Demo:

$ awk -f replace.awk filea fileb filec
Hello 111 toto 222 dear 111 trird BBBBBB tuizf 111 dfdsf 333

A solution for sehe:

FILENAME==ARGV[1] {              # Read the first file passed in
    find[FNR]=$0                 # Create a hash of words to replace
    next                         # Get the next line in the current file
}
FILENAME==ARGV[2] {              # Read the second file passed in
    replace[find[FNR]]=$0        # Hash find words by the words to replace them 
    next                         # Get the next line in the current file
}
{                                # Read any other file passed in (i.e third)
    for (i=1;i<=NF;i++) {        # Loop over all field & do replacement if needed
        printf "%s%s",(replace[$i]?replace[$i]:$i),(i==NF?RS:FS)
    }
}

For replacements the ignore word boundaries:

$ cat replace.awk 
FILENAME==ARGV[1] {
    find[FNR]=$0
    next
}
FILENAME==ARGV[2] {
    replace[find[FNR]]=$0
    next
}
{
    for (word in find)
        gsub(find[word],replace[find[word]])
    print
}

Demo:

$ awk -f replace.awk filea fileb filec
Hello 111 toto 222 dear "111" trird 222B tuizf 111 dfdsf 333
like image 194
Chris Seymour Avatar answered Sep 20 '22 04:09

Chris Seymour


sed 's/.*/s/' fileA | paste -d/ - fileA fileB | sed 's/$/\//' | sed -f - fileC

and the correct and faster version would be

paste -d/ fileA fileB | sed 's/^/s\//;s/$/\/g/' | sed -f - fileC
like image 40
hipe Avatar answered Sep 22 '22 04:09

hipe


A two-phase rocket:

sed -e "$(paste file[AB] | sed 's/\(.*\)\t\(.*\)/s\/\1\/\2\/g;/')" fileC 

What this does is create an adhoc sed script using paste file[AB] | sed 's/\(.*\)\t\(.*\)/s\/\1\/\2\/g;/':

s/AAAAA/111/g;
s/BBBBB/222/g;
s/CCCCC/333/g;
s/DDDDD/444/g;

And then runs it with fileC as the input

like image 26
sehe Avatar answered Sep 22 '22 04:09

sehe