Grep строка точного соответствия с пробелами в качестве переменной

#awk #grep

#awk #grep

Вопрос:

У меня есть:

 file.csv
  

Которая содержит

 2,1,"string with spaces",3,4,5
2,1,"some other string",3,4,5
2,1,"string with spaces more than this",3,4,5
2,1,"yet another",3,4,5
2,1,"string with spaces too",3,4,5
  

Когда я делаю это:

grep '"string with spaces",' file.csv

Это приводит к желаемому результату, который является:

 2,1,"string with spaces",3,4,5
  

Теперь мне нужно сделать это в цикле while:

 while read p; do

    grep '"$p",' file.csv

done < list.txt
  

Где:

 list.txt
  

содержит:

 string with spaces
yet another
  

И мой желаемый результат:

 2,1,"string with spaces",3,4,5
2,1,"yet another",3,4,5
  

Проблема в том, что мой цикл while возвращается пустым или совпадает частично. Как мне выполнить цикл list.txt и получить желаемый результат?

Комментарии:

1. Делать это с помощью grep многократного вызова цикла крайне неэффективно, вы могли бы сделать все это за один вызов awk.

Ответ №1:

Если вы согласны с awk , это должно быть легко для него.

 awk 'FNR==NR{a[$0];next} ($4 in a)' list.txt FS="[,"]" file.csv
  

ИЛИ (согласно комментарию Ed sir, чтобы сделать разделитель полей запятой и сделать его более понятным, можно попробовать следующее)

 awk -F, 'FNR==NR{a["""$0"""];next} $3 in a' list.txt file.csv
  

Вывод будет следующим.

 2,1,"string with spaces",3,4,5
2,1,"yet another",3,4,5
  

Комментарии:

1. Это должно быть awk -F, 'FNR==NR{a["""$0"""];next} $3 in a' list.txt file.csv , чтобы избежать ошибок, когда поле, заключенное в кавычки, содержит запятые

2. @EdMorton, конечно, сэр, добавил это сейчас, спасибо, что дали мне знать.

3. Хм, на самом деле вам нужно было бы использовать FPAT (или другой подход (например, с match($0,/»[^»]*»/)) чтобы сделать ее надежной, даже с предложенным мной изменением она все равно завершится неудачей, если поле, заключенное в кавычки, будет содержать запятые.

4. Не стоит, поскольку OP уже принял другой ответ.

5. @EdMorton Я допустил ошибку, приняв ответ от @marcus. Я пошел внедрять его решение, и оно сработало. Однако мой list.txt имеет 27 тысяч строк, а затем file.csv имеет 1000 тысяч строк. grep все шло очень медленно. Я вернулся сюда и нашел ваш ответ, который @ravindersingh13 добавил к своему ответу. И ваш сработал менее чем за 5 секунд. Я не понимаю, как работает awk, но мое решение с grep , возможно, заняло несколько дней.

Ответ №2:

Все ваши строковые кавычки заключены в одинарные кавычки, ' которые не выполняют никакой интерполяции $p переменной. Изменение ее на grep '"'"$p"'",' file.csv решит проблему. Ключ в том, что здесь интерполяция переменной выполняется внутри двойных кавычек " , а затем объединяется со строками, содержащими фактические символы двойных кавычек " .

Более (или менее, в зависимости от вашей точки зрения) читаемая версия может выглядеть следующим образом: grep ""$p"," file.csv

Комментарии:

1. Это работает отлично. Мне нравится grep ""$p"," file.csv версия, поскольку она более читабельна.

Ответ №3:

  grep -Ff strings.txt file.csv
  

Этого должно хватить.