Как удалить содержимое файла B из файла A - возможны дубликаты - PullRequest
1 голос
/ 05 апреля 2019

Сначала мне нужно сделать немного фона, может быть, есть какое-то более простое решение, но посмотрим.

Итак, у меня есть файл в определенном формате (столбцы) и в порядке, который содержит имена документов. Этот файл содержит более 850000 строк. Моей первоначальной задачей было найти все документы, которые нужно удалить. Обычно эти документы имеют некоторое числовое значение в последнем столбце, как, например, VC99. Поэтому моей задачей было удалить каждый документ, помеченный этим значением VC. Документы начинаются с заглавных букв и имеют некоторое число в четвертом столбце, например 04. Чтобы определить, где заканчивается этот документ, мне нужно было найти строку, которая начинается с двух или более заглавных букв и имеет конкретное значение для столбца (равное или меньшее предыдущего) , Например, как вы можете видеть ниже, документ начинается с ABC 101 ... и его значение в четвертом столбце равно 04, а в последнем столбце он помечен как VC99, поэтому мне нужно удалить его из файла со всеми вложенными документами.

ABC 101 11/11   =       R1A     04      BLABLABLA BLAAAA  ASDDSASDA SADDA           VC22!VC23!VC24!VC25!VC26!VC99!VC27!VC28!VC29!VC30
9476-ABC 555 55/55              B2Z
345 34-BGF 957 22/55            A       3       FREE    ASDADADADADAD.
1551-YTR 101 41/15              A       4/3     FREE    ADADADADADADADADADADADADA              XP1
123 00-DFG 111 11               D       4/3     FREE    ADASDADASDASDADADADAD
1/190 06-YTR 101 11             D       4/3     FREE    ASDADADASD ADADADA ASDADADASDA ADSADADADA
BFD 290 01/28   =       D4B     05      BLABLABLA       
1095-ANT 290 01/28              G2Z
131 61-ANT 290 01/28            A       3       FREE    SASDADADADADAD.
1551-ANT 290 01/27              A       4/3     FREE    SASDADADAASDADADADADASDADADADADAD       XP1
1/155 18-ANT 290 01/10          A       4/3     FREE    ASDADADADADAD             XP1
21/155 18-ANT 290 01/21         A       4/1     FREE    ASDADADADADADASDADADADADAD
DFT 290 9985    =       T4      03      BLOCK   APCLOB  XIG/DO
1095-DFG 290 9985               R2
1551-DFG 290 9985               B       1/7     FREE    ASDADADADADAD
1/1551-DFG 290 9985             B       1/7     FREE    FASDADADADADADARASDADADADADAD AASDADADADADADOB
2/155 18-DFG 290 9985           A       1/L     FREE    AASDADADADADAD PASDADADADADAD CASDADADADADAD ASDADADADADAD
1/190 83-DFG 290 9985           A       1/L     FREE    APASDADADADADADON PASDADADADADADL ASDADADADADAD ASDADADADADAD
131 61-DFG 290 9985             B       3       FREE    SASDADADADADADPEC.
DZZB 987 2242   =       F5Y     04      SOFTWARE UNIT   APCLOBU XIG/DO
1095-DFGY 987 2242              R2A
190 55-DFGY 987 2242            J       1/2/7   FREE    SASDADADADADADO.
155 14-DFGY 987 2242            D       2/7     FREE    APASDADADADADADURV
2/109 26-DFGY 987 2242          B       3/7     FREE    CHAASDADADADADADTION
5/109 26-DFGY 987 2242          D       3/7     FREE    CHASDADADADADADRMAASDADADADADADON
190 73-DFGY 987 2242            B       3/7     FREE    AASDADADADADADRAM
152 01-DFGY 987 2242            -----   B
ZXC 290 0004    =       T5      03      FUNCTION BLOCK  CAPPGEN XIG/D           VC22!VC23!VC24!VC25!VC26!VC99!VC27!VC28!VC29!VC30
1095-DFG 290 0004               R2
2/155 18-DFG 290 0004           B       1/L     FREE    CAPASDADADADADADN
131 61-DFG 290 0004             B       3       FREE    STRUASDADADADADADC.
1551-DFG 216 2530               B       4/1/7   FREE    BLOASDADADADADADNTING
1/1551-DFG 216 2530             B       4/1/7   FREE    BLOCASDADADADADADHART
1/190 83-DFG 216 1642           J       4/1/L   FREE    CALASDADADADADADTHASDADADADADADCASDADADADADADG
DFFT 987 9426   =       D5W     02      SOFTWARE UNIT   CAASDADADADADADNU        XIG/DO
1095-DFGY 987 9426              DF2
190 55-DFGY 987 9426            E       1/2/7   FREE    CAASDADADADADADAM
155 14-DFGY 987 9426            C       2/7     FREE    CAPPASDADADADADADRV
3/109 26-DFGY 987 9426          C       3/7     FREE    CHAASDADADADADADTION
4/109 26-DFGY 987 9426          C       3/7     FREE    CASDADADADADADON
5/109 26-DFGY 987 9426          B       3/7     FREE    CHASDADADADADADTION
190 73-DFGY 987 9426            D       3/7     FREE    CAASDADADADADADAM
152 01-DFGY 987 9426            ZX4     B
1/1521-DFGY 987 9426            C       3/7     FREE    BLASDADADADADADASDADADADADADASDADADADADADINT
2/152 83-DFGY 987 9426          B       3/7     FREE    BAASDADADADADADDADADADADASDADADADADADPORASDADADADADADPGEN

В этом примере каждая строка, начиная с ABC 101 11/11 до DFT 290 9985, должна быть удалена. И затем снова все, начиная с ZXC 290 0004 до DFFT 987 9426 должно быть удалено. По сути, мы можем сказать, что я хочу удалить что-нибудь между двумя шаблонами, и вот как я начал.

Моя общая идея состояла в том, чтобы извлечь все имена документов, отмеченные VC99, со значением из четвертого столбца, и я сделал это с помощью этой команды

grep "^[A-Z][A-Z].*=.*0[0-7].*V.[9-9][9-9].*" base.txt | awk -F "\t" {'printf ("%5s\t%s\n", $1, $4)'} > delete

В этот момент у меня был файл с именем delete с двумя значениями имени документа и присвоенного ему значения, и он выглядит так

ABC 101 11/11   04
ZXC 290 0004    03

К сожалению, многие имена содержат косые черты, поэтому я не мог легко передать их моей следующей команде awk, и это был первый удар на дороге, но я нашел решение для этого. Я использовал sed, чтобы экранировать косые черты несколько раз, чтобы сработала следующая команда awk.

sed 's#/#\\\\/#g' delete > delete_fixed

Теперь мой исправленный файл выглядел так

ABC 101 11\\/11 04
ZXC 290 0004    03

Теперь я смог передать эти переменные в awk и найти шаблон, используя этот маленький скрипт, который я частично нашел на этом портале.

while IFS=$'\t' read var1 var2
do
awk -F "\t" '/^'"$var1"'/{flag=1;print;next}/^[A-Z][A-Z]/ && ($4 <= '"$var2"'){flag=0}flag' base.txt >> output
done < delete_fixed

После нескольких тестов я был уверен, что у меня есть полный список строк, которые мне нужно удалить из моего base.txt, который для этого примера выглядит следующим образом

ABC 101 11/11   =       R1A     04      BLABLABLA BLAAAA  ASDDSASDA SADDA           VC22!VC23!VC24!VC25!VC26!VC99!VC27!VC28!VC29!VC30
9476-ABC 555 55/55              B2Z
345 34-BGF 957 22/55            A       3       FREE    ASDADADADADAD.
1551-YTR 101 41/15              A       4/3     FREE    ADADADADADADADADADADADADA              XP1
123 00-DFG 111 11               D       4/3     FREE    ADASDADASDASDADADADAD
1/190 06-YTR 101 11             D       4/3     FREE    ASDADADASD ADADADA ASDADADASDA ADSADADADA
BFD 290 01/28   =       D4B     05      BLABLABLA       
1095-ANT 290 01/28              G2Z
131 61-ANT 290 01/28            A       3       FREE    SASDADADADADAD.
1551-ANT 290 01/27              A       4/3     FREE    SASDADADAASDADADADADASDADADADADAD       XP1
1/155 18-ANT 290 01/10          A       4/3     FREE    ASDADADADADAD             XP1
21/155 18-ANT 290 01/21         A       4/1     FREE    ASDADADADADADASDADADADADAD
ZXC 290 0004    =       T5      03      FUNCTION BLOCK  CAPPGEN XIG/D           VC22!VC23!VC24!VC25!VC26!VC99!VC27!VC28!VC29!VC30
1095-DFG 290 0004               R2
2/155 18-DFG 290 0004           B       1/L     FREE    CAPASDADADADADADN
131 61-DFG 290 0004             B       3       FREE    STRUASDADADADADADC.
1551-DFG 216 2530               B       4/1/7   FREE    BLOASDADADADADADNTING
1/1551-DFG 216 2530             B       4/1/7   FREE    BLOCASDADADADADADHART
1/190 83-DFG 216 1642           J       4/1/L   FREE    CALASDADADADADADTHASDADADADADADCASDADADADADADG

И, как вы можете предположить, судя по плитке, я застрял. Я не знаю, как удалить эти точные строки из моего файла base.txt. Я пробовал grep

grep -F -x -v -f output base.txt > final

но он слишком жадный и удаляет слишком много, возможно, из-за дубликатов.

Хуже всего то, что я не могу ни отсортировать этот файл, ни изменить его структуру, потому что этот файл будет импортирован в другой инструмент, поэтому я могу удалить только строки.

Я также пробовал использовать diff, чтобы увидеть только различия, но в диссе добавляются некоторые символы и изменяется структура (или я не знаю, как правильно его использовать).

Моя идея состоит в том, чтобы как-то начать удаление со строки, которая сначала точно совпадает, а затем перейти вниз и не возвращаться к началу файла или что-то в этом роде. Или, может быть, есть способ сделать это вместе с моим поиском по шаблону awk?

Буду благодарен за любые советы на данный момент.

1 Ответ

0 голосов
/ 06 апреля 2019

Вы можете разобрать логику в awk гораздо проще, чем делать это с несколькими инструментами. следующий код awk проверит строки заголовка документа / вложенного документа, а затем установит флаг (skip), чтобы определить, следует ли пропустить или напечатать строку.

$ cat t.15.awk
BEGIN { FS = OFS = "\t"; }

# document/subdocument header started with at least two Uppercase letters 
# and only contain numbers in the 4th field.
function is_document_header() {
    return /^[A-Z][A-Z]/ && $4 ~ /^[0-9]+$/
}

# the target document header must have VC99 as a standalone word in the last column
function has_vc99() {
    return $NF ~ /\<VC99\>/
}

# find the line matching document/subdocument header, flag it accordingly
is_document_header() {
    # set up the skip flag
    skip = has_vc99() ? 1 : $4 <= prev_f4 ? 0 : skip;

    # save $4 in the previous docuement header to prev_f4, remove
    # the if(..) condition if sub-documents also counted
    if (has_vc99()) prev_f4 = $4;
}

# print only when skip is 0
!skip { print }

затем запустите команду awk:

$ awk -f t.15.awk file.txt

КСТАТИ. в вашем примере текста первый документ, начинающийся с ABC 101, не содержит VC99.

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