![Удалить строки с повторяющимся первым полем/столбцом из большого файла](https://rvso.com/image/164735/%D0%A3%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C%20%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8%20%D1%81%20%D0%BF%D0%BE%D0%B2%D1%82%D0%BE%D1%80%D1%8F%D1%8E%D1%89%D0%B8%D0%BC%D1%81%D1%8F%20%D0%BF%D0%B5%D1%80%D0%B2%D1%8B%D0%BC%20%D0%BF%D0%BE%D0%BB%D0%B5%D0%BC%2F%D1%81%D1%82%D0%BE%D0%BB%D0%B1%D1%86%D0%BE%D0%BC%20%D0%B8%D0%B7%20%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%BE%D0%B3%D0%BE%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B0.png)
У меня очень большой файл (фрагмент ниже). Мне нужно удалить все строки, где число в первом столбце не увеличивается последовательно от строки выше.
Например, я хочу сохранить первую строку из моего фрагмента, где идентификатор в первом столбце — « » 40812
. Затем я хочу сохранить строку, где « 40813
» находится в первом столбце (строка 3 в моем примере), а затем строку, которая начинается с « 40814
», и т. д. Я хочу удалить все строки, которые нарушают эту последовательность, например, вторую строку.
Я посмотрел здесь на предыдущие вопросы/ответы на возможные решения и пока не добился успеха. Решение, которое появилось в нескольких вопросах, это:
awk -F',' ' '!seen[$1]++ myFile
Я адаптировал другое решение, которое я видел, как:
sort -t':' -k 1,1 -u myFile
Если кто-нибудь может мне подсказать, где я ошибаюсь, я буду очень благодарен. Я не очень опытен в работе с файлами.
40812 20406.000000 0.843859468 1083.209050130 -994.562279080 -993.349611938 22.120868921
40829 20414.500000 0.891283743 1144.084593627 -994.539001565 -993.349739827 21.177788019
40813 20406.500000 0.829362077 1064.599666089 -994.546948121 -993.348764740 22.087239027
40830 20415.000000 0.889606427 1141.931529727 -994.537943593 -993.350242614 21.282490969
40814 20407.000000 0.822524589 1055.822814442 -994.540118434 -993.348757318 22.083606005
40831 20415.500000 0.875230513 1123.478077086 -994.523844766 -993.350421831 20.606467962
40815 20407.500000 0.823511602 1057.089780943 -994.541681744 -993.349315083 22.432111979
40832 20416.000000 0.846150258 1086.149592126 -994.494220141 -993.349798791 22.309054136
40816 20408.000000 0.824550451 1058.423286012 -994.543159511 -993.349731194 22.481428146
40833 20416.500000 0.811604775 1041.805740021 -994.458563132 -993.348626225 21.118428946
40834 20417.000000 0.787796672 1011.244783236 -994.434062658 -993.347887110 20.963790894
40817 20408.500000 0.819160081 1051.504008955 -994.537767061 -993.349702160 22.268819809
40835 20417.500000 0.784857495 1007.471947645 -994.431441227 -993.348167742 20.731789112
40818 20409.000000 0.807571275 1036.628191427 -994.525675417 -993.349169067 22.332761049
40836 20418.000000 0.799208319 1025.893192994 -994.446595759 -993.348938468 21.268665075
40819 20409.500000 0.797104599 1023.192780242 -994.514563564 -993.348491176 22.622548103
40837 20418.500000 0.819797939 1052.322786256 -994.467698852 -993.349417295 21.013041973
40820 20410.000000 0.796605925 1022.552664951 -994.513928312 -993.348319789 22.193170071
решение1
Это именно то, что awk
отлично подходит для:
$ awk '{ if(NR==1 || $1 == last+1){print; last=$1}}' file
40812 20406.000000 0.843859468 1083.209050130 -994.562279080 -993.349611938 22.120868921
40813 20406.500000 0.829362077 1064.599666089 -994.546948121 -993.348764740 22.087239027
40814 20407.000000 0.822524589 1055.822814442 -994.540118434 -993.348757318 22.083606005
40815 20407.500000 0.823511602 1057.089780943 -994.541681744 -993.349315083 22.432111979
40816 20408.000000 0.824550451 1058.423286012 -994.543159511 -993.349731194 22.481428146
40817 20408.500000 0.819160081 1051.504008955 -994.537767061 -993.349702160 22.268819809
40818 20409.000000 0.807571275 1036.628191427 -994.525675417 -993.349169067 22.332761049
40819 20409.500000 0.797104599 1023.192780242 -994.514563564 -993.348491176 22.622548103
40820 20410.000000 0.796605925 1022.552664951 -994.513928312 -993.348319789 22.193170071
Или немного гольфа:
$ awk '(NR==1 || $1 == last+1) && last=$1' file
40812 20406.000000 0.843859468 1083.209050130 -994.562279080 -993.349611938 22.120868921
40813 20406.500000 0.829362077 1064.599666089 -994.546948121 -993.348764740 22.087239027
40814 20407.000000 0.822524589 1055.822814442 -994.540118434 -993.348757318 22.083606005
40815 20407.500000 0.823511602 1057.089780943 -994.541681744 -993.349315083 22.432111979
40816 20408.000000 0.824550451 1058.423286012 -994.543159511 -993.349731194 22.481428146
40817 20408.500000 0.819160081 1051.504008955 -994.537767061 -993.349702160 22.268819809
40818 20409.000000 0.807571275 1036.628191427 -994.525675417 -993.349169067 22.332761049
40819 20409.500000 0.797104599 1023.192780242 -994.514563564 -993.348491176 22.622548103
40820 20410.000000 0.796605925 1022.552664951 -994.513928312 -993.348319789 22.193170071
Объяснение
if(NR==1 || $1 == last+1)
:NR
— это номер текущей строки. ПоэтомуNR == 1
будет истинным только при чтении первой строки файла. Нам это нужно, чтобы мы всегда печатали первую строку. Затем,$1 == last +1
будет истинным, если первое поле строки ($1
) равно значению, сохраненному в переменной,last
плюс 1. В совокупности это означает «если это последняя строка или если первое поле равно last + 1», что определяет ваши целевые строки.print; last=$1
: Если одно из двух условий, описанных выше, верно, выведите строку и установите значение вlast
качестве первого поляэтотлинию, чтобы мы могли обработать следующую.