Как заменить оператор for for путем сопоставления разных файлов в сценарии shell / bash - PullRequest
1 голос
/ 29 мая 2019

С помощью моего сценария оболочки я пытаюсь сопоставить 2 разных файла и заменить вхождения в File1 на строки File2:

File1 occurency 1 <-- File2 row 1
File1 occurency 2 <-- File2 row 2
File1 occurency 3 <-- File2 row 3
...

Количество строк в файле 2 равно числам в файле 1, поскольку изначально они были взяты из файла 1

Файл1 - это файл Json

...
"@type" : "Review",
"@id":"https://google.com/social/profile/xxxxxxx.jpg"
"datePublished" : "Tue Sep 18 16:32:53 CEST 2012",

"@type" : "Review",
"@id":"https://google.com/social/profile/xxxxxxx.jpg"
"datePublished" : "Tue Sep 18 16:32:53 CEST 2012",
 ...

File2 - это форматированный "json like" файл

"profilePhoto":"https://someurl.ltd/aaaa_90.jpg"
"profilePhoto":"https://someurl.ltd/bbbb_90.jpg"
"profilePhoto":"https://someurl.ltd/cccc_90.jpg"
 ....

На самом деле та часть скрипта, которая должна выполнять эту работу, выглядит как

IFS=$'\n'
set -f
for i in $(cat < File2.txt); do

sed -i "s|.*social.*|$i|g" File1.json

done

Этот скрипт заменяет все вхождения в File1 на первую строку File2, поэтому во втором цикле больше нет совпадений для поиска. пример вывода

...
"@type" : "Review",
"profilePhoto":"https://someurl.ltd/cccc_90.jpg"
"datePublished" : "Tue Sep 18 16:32:53 CEST 2012",

"@type" : "Review",
"profilePhoto":"https://someurl.ltd/cccc_90.jpg"
"datePublished" : "Tue Sep 18 16:32:53 CEST 2012",
 ...

Мне нужен вывод, как этот

...
"@type" : "Review",
*"profilePhoto":"https://someurl.ltd/**aaaa**_90.jpg"*
"datePublished" : "Tue Sep 18 16:32:53 CEST 2012",

"@type" : "Review",
*"profilePhoto":"https://someurl.ltd/**bbbb**_90.jpg"*
"datePublished" : "Tue Sep 18 16:32:53 CEST 2012",
 ...

Заранее благодарю за любую помощь.

Ответы [ 3 ]

1 голос
/ 29 мая 2019

Это может сработать для вас (GNU sed):

sed -e '/xxxxxxx\.jpg/R file2' -e '//d' file1

Это заменяет каждую строку, содержащую xxxxxxx.jpg, строкой из файла 2.

1 голос
/ 29 мая 2019

Редактировать:

После просмотра того, что вы хотите получить намного ближе, я пришел к этому

for i in $(sed 's/^/*/;s|ltd/|&**|;s|_|**&|;s/$/*/' File2.txt); do awk -i inplace -v i="$i" 'NR==1,/.*social.*/{sub(/.*social.*/, i)} 1' File1.json; done

Как только вы ограничите замену в File1.json только первым вхождением, которое вы можетепозвольте циклу работать на вас.

Чтобы сломать его

# Instead of cat file I tackled substitution for each line in File2.txt as $i
for i in $(sed 's/^/*/;s|ltd/|&**|;s|_|**&|;s/$/*/' File2.txt); do

    # Here awk sub only first occurrence to not overwrite whole file
    # Second loop will handle the next occurrence with second line from File2.txt  
    # And third ect.. ect..
    awk -i inplace -v i="$i" 'NR==1,/.*social.*/{sub(/.*social.*/, i)} 1' File1.json
done     

Все ниже, если ваша версия awk не поддерживает -i на месте, то вам придется сделать это

awk -v i="$i" 'NR==1,/.*social.*/{sub(/.*social.*/, i)} 1 { rec = rec $0 RS } END { close(FILENAME); printf "%s", rec > FILENAME }' File1.json

Таким образом, все будет выглядеть так:

 # Instead of cat file I tackled substitution for each line in File2.txt as $i
for i in $(sed 's/^/*/;s|ltd/|&**|;s|_|**&|;s/$/*/' File2.txt); do

    # Here awk sub only first occurrence to not overwrite whole file
    # Second loop will handle the next occurrence with second line from File2.txt  
    # And third ect.. ect..
    awk -v i="$i" 'NR==1,/.*social.*/{sub(/.*social.*/, i)} 1 { rec = rec $0 RS } END { close(FILENAME); printf "%s", rec > FILENAME }' File1.json
done

Наконец, если ни одна из вышеперечисленных команд awk не работает, вы можете получить временные файлы.

awk -v i="$i" 'NR==1,/.*social.*/{sub(/.*social.*/, i)} 1' File1.json > tmpfile && mv tmpfile File1.json

, поэтомувсе это будет выглядеть так

for i in `cat File2.txt`; do

 awk -v i="$i" 'NR==1,/.*social.*/{sub(/.*social.*/, i)} 1' File1.json > tmpfile && mv tmpfile File1.json

done
0 голосов
/ 29 мая 2019

Спасибо всем, ребята!

После проверки предложения @goose я просто внес небольшое изменение и окончательное решение, которое работает для этой проблемы -

for i in `cat jsonlike.txt`; do

awk -v i="$i" 'NR==1,/.*social.*/{sub(/.*social.*/, i)} 1 { rec = rec $0 RS } END { close(FILENAME); printf "%s", rec > FILENAME }' File1.json

done

Я знаю, что это можно сделать и с помощью цикла while, но это нормально, даже для меня. спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...