Удалить строку (пропустить из вывода), если предыдущая строка является префиксом - PullRequest
0 голосов
/ 27 мая 2018

Это очень похоже на вопрос " удалить повторяющиеся строки с аналогичным префиксом ", но все наоборот:

При условии ввода отсортированных строк (в этом случае каталоги), например:

a/
a/b/c/
a/d/
bar/foo/
bar/foo2/
c/d/
c/d/e/

Я хочу удалить строки из вывода, , если предыдущая строка является префиксом текущей строки .В этом случае вывод будет:

a/
bar/foo/
bar/foo2/
c/d/

Это было бы довольно просто для программирования на Python и т. Д., Но в этом случае я нахожусь в среде оболочки (bash, sort, sed, awk ...),(Пересортировка в порядке.)

Ответы [ 4 ]

0 голосов
/ 27 мая 2018
$ awk 'NR==1 || index($0,prev)!=1{prev=$0; print}' file
a/
bar/foo/
bar/foo2/
c/d/
0 голосов
/ 27 мая 2018

используйте awk:

awk '{if(k && match($0, k))next; k="^"$0}1' file

k = "^" $ 0, чтобы привязать шаблон к началу строки.

Возможно, потребуется NF>0 перед основным блоком, если естьявляются ПУСТЫМИ строками.

Обновление: Могут возникнуть проблемы, если в переменной k существуют метасимволы регулярного выражения, строка ниже без использования регулярного выражения должна быть лучше:

awk '{if(k && index($0, k)==1)next; k=$0}1' file

Обновление-2: спасибо @Ed, я настроил 2-й метод, чтобы он охватывал непустые строки с нулями (пустые строки будут сохранены как есть):

awk '{if(k!="" && index($0,k)==1)next;k=$0}1' file
0 голосов
/ 27 мая 2018

Сам Bash (фактически оболочка POSIX) предоставляет все, что вам нужно, через расширение параметра с удалением подстроки .Все, что вам нужно сделать, это проверить, совпадает ли прочитанная вами строка с удаленным префиксом.Если это не так, у вас есть строка с префиксом, в противном случае, у вас есть строка без префикса.Тогда достаточно просто вывести строку без префикса и установить префикс для текущей строки - и повторить, например,

#!/bin/bash

pfx=    ## prefix

## read each line
while read -r line; do 
    ## if no prefix or line matches line with prefix removed
    if [ -z "$pfx" -o "$line" = "${line#$pfx}" ]
    then
        printf "%s\n" "$line"   ## output lile
        pfx="$line"             ## set prefix to line
    fi
done < "$1"

( примечание: , если есть вероятностьчто во входном файле, который не содержит конца файла POSIX, например, '\n' в последней строке файла, вы должны проверить содержимое строки как условие вашего while, например, while read -r line || [ -n "$line" ]; do ...)

Пример входного файла

$ cat string.txt
a/
a/b/c/
a/d/
bar/foo/
bar/foo2/
c/d/
c/d/e/

Пример использования / Вывод

$ bash nonprefix.sh string.txt
a/
bar/foo/
bar/foo2/
c/d/
0 голосов
/ 27 мая 2018

Perl 1-лайнер.Обведите все входные строки -n, а затем выполните -e следующую программу, проверив, соответствует ли начало текущей строки последней строке, и напечатав несоответствия.

perl -ne 'print unless m|^$last|; chomp($last=$_);' file_list.txt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...