#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
Этого должно хватить.