как искать строку из одного файла и обновлять другой в Linux - PullRequest
0 голосов
/ 18 февраля 2019

У меня есть два файла. Я ищу строки по одному в одном файле и обновляю запись в другом файле.Скажем, у меня есть текстовый файл A.csv

TABLE1, ABC_STRING
TABLE2, ABC_STRING
TABLE3, ABC_STRING

B.csv

TABLEA,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLEB,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLE1,SOMEVALUE,ABC_INT,NULL,ABC_INT
TABLEC,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLE2,SOMEVALUE,ABC_INT,NULL,ABC_INT
TABLE3,SOMEVALUE,ABC_INT,NULL,ABC_INT

Ожидается вывод в новом файле, например:

TABLEA,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLEB,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLE1,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLEC,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLE2,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLE3,SOMEVALUE,ABC_STRING,NULL,ABC_STRING

Я пробовал какthis:

for i in $(grep -w "ABC_STRING" A.csv | awk -F ',' '{print $1}'); do
grep -w "$i" B.csv | sed 's/ABC_INT/ABC_STRING/g'
done | more

Я не уверен, как написать команду для копирования каждой строки, проверить, содержит ли она строку, если она доступна, заменить и записать ее в C.csv, если не записать ее втот же C.csv.Может ли кто-нибудь предоставить фрагмент кода для моего требования.

Ответы [ 3 ]

0 голосов
/ 18 февраля 2019

Вы можете попробовать Perl

perl -pe ' 
         BEGIN { %kv=map{chomp;split(",")} qx(cat A.csv) }  
         /^(.+?),/ and $kv{$1} and s/ABC_INT/ABC_STRING/g 
'

, используя данные входные данные

$  perl -pe ' BEGIN {%kv=map{chomp;split(",")} qx(cat A.csv)}  /^(.+?),/ and $kv{$1} and s/ABC_INT/ABC_STRING/g ' B.csv
TABLEA,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLEB,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLE1,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLEC,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLE2,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLE3,SOMEVALUE,ABC_STRING,NULL,ABC_STRING

$
0 голосов
/ 19 февраля 2019

Потому что unix

cat <<EOF >A.csv
TABLE1, ABC_STRING
TABLE2, ABC_STRING
TABLE3, ABC_STRING
EOF

cat <<EOF >B.csv
TABLEA,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLEB,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLE1,SOMEVALUE,ABC_INT,NULL,ABC_INT
TABLEC,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
TABLE2,SOMEVALUE,ABC_INT,NULL,ABC_INT
TABLE3,SOMEVALUE,ABC_INT,NULL,ABC_INT
EOF


# join the first file on the first field
# with the second file on the second field
# print unmatched lines from the second file
# the unknown matches are substituted with ##
# the output is complicated - we output the matched correct line (6 fields)
# and after it we output the original second file (6 fields)
# when there is no match, the last field from the correct line 
# is the empty separator '##' 
# we can filter is later with sed
join -11 -22 -t, -a2 -e'##' -o 2.1,2.2,2.3,1.2,2.5,1.2,2.1,2.2,2.3,2.4,2.5,2.6 <(
    # dunno what the spaces are doing in A.csv, remove them
    <A.csv tr -d ' ' | 
    # sort the file on the first field
    sort -k1 -t,
) <(
    # add a number of the lines to the second file
    # so we can sort it like the original file later
    <B.csv nl -s, -w1 | 
    # sort it on the second field (the first field is the number now)
    sort -k2 -t,
) |
# here the output looks like: 
# 6,TABLE3,SOMEVALUE,ABC_STRING,NULL,ABC_STRING,6,TABLE3,SOMEVALUE,ABC_INT,NULL,ABC_INT
# 1,TABLEA,SOMEVALUE,##,NULL,##,1,TABLEA,SOMEVALUE,ABC_STRING,NULL,ABC_STRING
# remove the first 6 fields from the lines with `##,` they were not matched
sed 's/.*,##,//' |
# extract first 6 fields, less to sort, operation is cheap
cut -d, -f1-6 |
# sort on the field numerical. This is the numbers we inserted in the second file
sort -k1 -t, -n |
# extract 5 lines from the original
cut -d, -f2-6
0 голосов
/ 18 февраля 2019
awk -F', *' -v OFS=',' 'NR==FNR{m[$1]=$2; next} $1 in m{$3=$5=m[$1]} 1' A.csv B.csv > C.csv
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...