Используйте SED для удаления определенных строк, используя индекс с номерами строк для удаления - PullRequest
0 голосов
/ 05 июня 2018

Я получаю большой файл, назовите его file.txt, который может иметь 20000 строк или более.Некоторые из этих строк должны быть удалены из исходного файла, и должен быть создан новый файл, содержащий оставшиеся строки, например, newfile.txt.Строки, которые нужно удалить, находятся в другом файле, например, index.txt.Итак, что-то вроде:

file.txt:

line1
line2
...
line19999
line20000

index.txt

11
56
79
...
19856

Я пытался использовать sed, пытаясь получитьиспользовать числа в индексе для удаления этих строк, например:

for i in ${index.txt[@]}
do
    sed -i.back '${i}d' file.txt>newfile.txt
done

Однако я получаю сообщение об ошибке: $ {index.txt [@]}: плохая замена, и у меня нетИдея как это исправить.

Я также пытался использовать gawk, но в коде было что-то не так, я думаю, что это связано с тем, что файл имеет отступ с вкладками.Если бы кто-то мог помочь, я очень ценю это.

Ответы [ 3 ]

0 голосов
/ 05 июня 2018

Do not вызовите sed в цикле, который будет очень медленным.

Вы можете преобразовать индексный файл в скрипт sed, а затем вызвать sed один раз для файла данных:

sed -i.bak "$(sed 's/$/d/' index.txt)" file.txt

Или, как указывает @ Hazzard17, игнорировать строки, которые не содержат только цифры:

script=$(sed -n '/^[[:blank:]]*[[:digit:]]\+[[:blank:]]*$/ s/$/d/p' index.txt)
sed -i.bak "$script" file.txt

демо:

$ seq 20000 | sed 's/^/line/' > file.txt
$ wc file.txt
 20000  20000 188894 file.txt
$ seq 20000 | while read n; do [[ $RANDOM -le 5000 ]] && echo $n; done > index.txt
$ wc index.txt
 3083  3083 16789 index.txt
$ sed -i.bak "$(sed 's/$/d/' index.txt)" file.txt
$ wc -l file.txt{,.bak}
 16917 file.txt
 20000 file.txt.bak
 36917 total

Чтобы прочитать файл в массив, вы можете сделать:

mapfile -t indices < index.txt
for i in "${indices[@]}"; do ...; done

или просто перебрать файл

while IFS= read -r i; do ...; done < index.txt
0 голосов
/ 05 июня 2018

Вот решение, которое не изменяет ваш index.txt и выводит результаты в newfile.txt:

#replace new lines in the file with "d;"
#After this, linenumbers will contain "11d;56d;79d;..."
linenumbers=$(tr '\n' ';' < index.txt | sed 's/;/d;/g') 

#write file.txt with specified line numbers removed to newfile.txt
sed -e "$linenumbers" file.txt > newfile.txt
0 голосов
/ 05 июня 2018

После awk может вам в этом помочь.

awk 'FNR==NR{a[$0];next} !(FNR in a)' index.txt file1.txt

Учитывая, что в вашем файле file1.txt есть номер строки, которую нам нужно удалить из file1.txt.Также добавьте > temp_file && mv temp_file file1.txt на тот случай, если вы хотите сохранить вывод в файле Input_file (file1.txt).

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