Grep подход для удаления всех строк в файле, которые соответствуют любой строке в другом файле? - PullRequest
0 голосов
/ 14 марта 2020

У меня есть файл информации о камере, где каждая строка имеет уникальный идентификатор в формате

{"_id":{"$oid":"5b0cfa5845bb0c0004277e13"},"geometry":{"coordinates":[139.751,35.685]},"addEditBy":["dd53cbd9c5306b1baa103335c4b3e91d8b73386ba29124ea2b1d47a619c8c066877843cd8a7745ce31021a8d1548cf2a"],"legacy_cameraID":1,"type":"ip","source":"google","country":"JP","city":"Tokyo","is_active_image":false,"is_active_video":false,"utc_offset":32400,"timezone_id":"Japan Standard Time","timezone_name":"Japan Standard Time","reference_url":"101.110.193.152/","retrieval":{"ip":"101.110.193.152","port":"80","video_path":"/"},"__v":0}

У меня также есть список идентификаторов камер, которые я хочу удалить из исходного файла в формате:

5b182800751c3b00044514a9
5b1976b473569e00045dba59
5b197b1273569e00045ddf0f
5b1970cc73569e00045d94fc

Как я могу использовать grep или какую-либо другую утилиту командной строки, чтобы удалить все строки во входном файле с идентификатором, указанным во втором файле?

Ответы [ 4 ]

3 голосов
/ 14 марта 2020

Допустим, у вас есть файл с именем ids.txt, в котором есть все идентификаторы камеры, которые необходимо исключить из файла данных, который мы назовем data.json. Мы можем использовать опцию -f grep (сопоставить из файла) и опцию -v (выводить только несоответствующие строки) следующим образом:

grep -f ids.txt -v data.json 

grep будет выводить только строки data.json, которые не соответствуют ни одной строке в ids.txt.

1 голос
/ 14 марта 2020

Вы должны использовать json осведомленный инструмент. Вот скрипт GNU awk, который использует расширение json:

$ gawk '                                     # GNU awk
@load "json"                                 # load extension
NR==FNR {                                    # read oids to a hash
    oid[$0]
    next
}
{                                            # process json
    lines=lines $0                           # support multiline json form
    if(json_fromJSON(lines,data)!=0) {       # once json is complete
        if(!(data["_id"]["$oid"] in oid))    # test if oid in exclude list
            print                            # output if not
        lines=""                             # rinse for repeat
    }
}' oids json
0 голосов
/ 17 марта 2020

Предполагая, что ваш json файл всегда такой регулярный:

awk -F'"' 'NR==FNR{ids[$1]; next} !($6 in ids)' ids json
0 голосов
/ 14 марта 2020

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

Например:

#!/bin/bash
exec 3<info.txt
while IFS= read -r line <&3; do
  id="$(printf '%s' "${line}" | jq '._id."$oid"' | sed -e 's/"//g')"
  if ! grep -e "${id}" list.txt >/dev/null; then
    printf '%s\n' "${line}"
  fi
done >clean.txt
exec 3>&-

Где:

  1. info.txt - это файл с информацией о камере
  2. list.txt - это список нежелательных идентификаторов

Обратите внимание, что это не единственный способ, которым вы можно добиться этого, я использовал простой цикл так же, как po c.

Вы можете достичь этого, используя непосредственно jq, например:

#!/bin/bash
for id in $(jq '._id."$oid"' info.txt | sed -e 's/"//g'); do
  if ! grep -e "${id}" list.txt >/dev/null; then
    grep -e "${id}" info.txt
  fi
done >clean.txt

Обратите внимание, что во втором примере второй grep необходим, потому что вы никогда не берете всю строку файла into.txt, а только его идентификатор.

Кроме того, имейте в виду, что если у вас есть псевдоним типа alias grep='grep --color=always', это может привести к прерыванию вывода.

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