bash пока l oop не работает при использовании sed - PullRequest
1 голос
/ 20 января 2020

У меня возникла проблема с sed через некоторое время - l oop .using sed. Я хочу прочитать 2-й столбец file1, сравнить его с содержимым file2, и, если строка соответствует, я хочу заменить соответствующую строку file1 на file2 string.

Я пытался использовать следующий код, но он не возвращает никаких выходных данных.

cat file1 | while read a b; do
  sed -i "s/$b/$(grep $b file2)/g" file1 > file3;
done 

Пример ввода:

file_1 содержимое:

1 1234
2 8765

file2 содержание:

12345
34567
87654

Ожидаемый результат:

1 12345
2 87654

Ответы [ 2 ]

1 голос
/ 20 января 2020

Не могли бы вы попробовать следующее.

awk 'FNR==NR{a[$2]=$1;next} {for(i in a){if(match($0,"^"i)){print a[i],$0;continue}}}'  file1  file2

Добавление формы решения, отличного от одного вкладыша:

awk '
FNR==NR{
  a[$2]=$1
  next
}
{
  for(i in a){
    if(match($0,"^"i)){
      print a[i],$0
      continue
    }
  }
}
'  Input_file1  Input_file2

Объяснение: Добавление подробного объяснения для кода выше.

awk '                             ##Starting awk code from here.
FNR==NR{                          ##Checking condition if FNR==NR then do following.
  a[$2]=$1                        ##Creating array a whose index is $2 and value is $1.
  next                            ##next will skip all further statements from here.
}
{                                 ##Statements from here will run for 2nd Input_file only.
  for(i in a){                    ##Traversing through array a all elements here.
    if(match($0,"^"i)){           ##Checking condition if current line matches index of current item from array a then do following.
      print a[i],$0               ##Printing array a whose index is i and current line here.
      continue                    ##Again take cursor to for loop.
    }
  }
}
'  Input_file1  Input_file2       ##Mentioning all Input_file names here.
1 голос
/ 20 января 2020

Ваш скрипт очень неэффективен. Используя while-l oop, вы читаете каждую строку file1. Это N операций. В каждой строке, которую вы обрабатываете с параметром while l oop, вы повторно обрабатываете полный file1, что делает процесс N*N. Однако в седе вы grep file2 постоянно. Если file2 имеет M строк, это становится процессом N*N*M. Это очень неэффективно.

Кроме того, есть некоторые проблемы:

  • Вы обновили file1 на месте, потому что вы используете флаг -i. Обновление на месте не обеспечивает никакого вывода, поэтому file3 будет пустым.
  • Вы читаете file1 с while-l oop, и в то же время вы обновляете file1 с sed. Я не знаю, как это отреагирует, но я не верю, что это здорово.
  • Если $b не входит в file2, вы бы, согласно вашей логике c, имели бы строку только с одним столбцом. Это не то, что вы ожидаете.

Исправление вашего скрипта будет следующим:

while read -r a b; do
  c=$(grep "$b" file2)
  [[ "$c" == "" ]] || echo "$a $c"
done < file1 > file3

, который все еще не эффективен, но уже M*N. Лучший способ - использовать awk


note: как новичок, всегда анализировать ваш скрипт с http://www.shellcheck.net примечание: как профессионал, всегда анализируйте ваш сценарий с помощью http://www.shellcheck.net

...