Home > OS >  Script to look for a word in file1 and copy the next word and replace that in file2
Script to look for a word in file1 and copy the next word and replace that in file2

Time:04-23

I have file1

(1'a lot of singapore 1.2.3.4 'some other info',0,null, 12345),

(2,'a lot of brazil  4.2.3.1, 'some other info',0,null, 12345),

(3,'a lot of india 3.4.2.1, 'some other info',0,null, 12345),

(4,'a lot of laos 1.3.4.5, 'some other info',0,null, 12345),

(5,'a lot of china 1.2.3.5, 'some other info',0,null, 12345);

and file2

(1'a lot of singapore A.B.C.D 'some other info',0,null, 12345),

(2,'a lot of brazil E.F.G.H, 'some other info',0,null, 12345),

(3,'a lot of india H.I.J.K, 'some other info',0,null, 12345),

(4,'a lot of laos L.M.N.O, 'some other info',0,null, 12345),

(5,'a lot of china P.Q.R.S, 'some other info',0,null, 12345);

I have created a script but to copy and replace with LINE number but need input to look for SINGAPORE in file 1 and copy next word 1.2.3.4 and look for singapore in file2 and replace the next word here from 1.2.3.4 - A.B.C.D and the final file2 looks like this

(1'a lot of singapore 1.2.3.4 'some other info',0,null, 12345),

Python script or Awk or sed any script will be helpful.

So far I have created this to copy and replace line numbers

sed -i '2d' File2.txt
awk 'NR==5380{a=$0}NR==FNR{next}FNR==2{print a}1' file1.txt file2.txt

CodePudding user response:

I'm not sure it will work and it's the best solution, but you need something like this.

import re

def try_to_get_country_data(line, country):
    line_parts = line.split(',')
    part_with_data = line_parts[1]
    
    if (match := re.search(f'.* {country} (.*)', part_with_data)) is not None:
        return match.group(1)
    
    return None
    
if __name__ == "__main__":
    found_data = None
    country = 'singapore'

    with open('some_file.txt', 'r') as f:
        for line in f:
            if (found_data := try_to_get_country_data(line, country)) is not None:
                break

    if found_data is not None:
        with open('second_file.txt', 'r') as f2:
            data = f2.readlines()

        for i, line in enumerate(data):
            if (replaced_data := try_to_get_country_data(line, country)) is not None:
                data[i] = line.replace(replaced_data, found_data)
                break

        with open('second_file.txt', 'w') as f2:
            f2.writelines(data)

So, I've checked it, and it work if line pattern same for each line.

CodePudding user response:

Here is a simple Awk script to look for the replacement text from the first input file and replace the corresponding token in the second input file.

awk -v country="singapore" 'NR == FNR {
    for (i=2; i<=NF; i  ) if ($(i-1) == country) token = $i; next }
  $0 ~ country { for(i=2; i<=NF; i  ) if ($(i-1) == country) $i = token
    } 1' file1 file2 >newfile2

When we are reading file1, NR == FNR is true. We loop over the input tokens and check for one which matches country; if we find one, we set token to that value. This means that if there are multiple matches on the country keyword, the last one in the first input file will be extracted.

The next statement causes Awk to skip the rest of the script for this input file, so the lines from file1 are only read, and not processed further.

If we fall through to the last line, we are now reading file2. If we see a line which contains the keyword, we perform a substitution on the keyword after the country keyword. (This requires the keyword to be an isolated token, not a substring within a longer word etc.) The final 1 causes all lines which get this far to be printed back to standard output, thus generating a copy of the second file with any substitutions performed.

If you have any control over the data format used here, perhaps try to figure out a way to get the input in a less haphazard ad-hoc format, like JSON.

CodePudding user response:

In case you would like a short bash script and assuming that the structure of the files is constant you could try something like this:

country="singapore"
a=$(grep "${country}" file0 | awk '{print $5}')

if [[ "${a}" ]]
then
    b=$(grep -w "${country}" file1 | awk '{print $5}')
    sed "s/${country} ${b}/${country} ${a}/g" file1
fi

Find below the output of the script:

(1'a lot of singapore 1.2.3.4 'some other info',0,null, 12345),

(2,'a lot of brazil E.F.G.H, 'some other info',0,null, 12345),

(3,'a lot of india H.I.J.K, 'some other info',0,null, 12345),

(4,'a lot of laos L.M.N.O, 'some other info',0,null, 12345),

(5,'a lot of china P.Q.R.S, 'some other info',0,null, 12345);

Use sed -i in order to edit file1 in place.

In order to avoid reading the same file multiple times and reducing a little bit the readability, the initial approach may be easily refactored as follows:

country="singapore"
file0c=$(cat file0)
file1c=$(cat file1)

a=$(echo "${file1c}" | grep -w "${country}" | awk '{print $5}')

if [[ "${a}" ]]
then
    b=$(echo "${file1c}" | grep -w "${country}" | awk '{print $5}')
    echo "${file1c}" | sed "s/${country} ${b}/${country} ${a}/g" | 
    tee file1_new
fi
  • Related