У вас есть один зашифрованный раздел в Ubuntu, но, поскольку вы не знали, как вы его установили, самый простой способ избавиться от него — это:
Примечание¹:FAT32 не позволяет шифровать данные, поэтому вы не сможете случайно зашифровать их, не зная
Это печатает все слова в файле, которые не являются комбинациями каких-либо двух слов в файле:
$ awk '{one[NR]=$1} END{for (i=1;i<=length(one);i++) for (j=1;j<=length(one);j++) two[one[i] one[j]]; for (i=1;i<=length(one);i++) if (!(one[i] in two)) print one[i]}' file
alpha
beta
gama
zeta
Для тех, кто предпочитает разбивать команды на несколько строк:
awk '
{
one[NR]=$1
}
END{
for (i=1;i<=length(one);i++)
for (j=1;j<=length(one);j++)
two[one[i] one[j]]
for (i=1;i<=length(one);i++)
if (!(one[i] in two))
print one[i]
}' file
Давайте рассмотрим файл с похожими словами, но с комбинациями, иногда стоящими перед отдельными словами:
$ cat file2
alphabeta
alpha
gammaalpha
beta
gamma
Выполнение той же команды по-прежнему дает правильный результат:
$ awk '{one[NR]=$1} END{for (i=1;i<=length(one);i++) for (j=1;j<=length(one);j++) two[one[i] one[j]]; for (i=1;i<=length(one);i++) if (!(one[i] in two)) print one[i]}' file2
alpha
beta
gamma
one[NR]=$1
Это создает массив one
с ключами, являющимися номерами строк, NR
, и значениями, являющимися словом в этой строке.
END{...}
Команды в фигурных скобках выполняются после того, как мы закончили чтение файла. Эти команды состоят из двух циклов. Этот первый цикл:
for (i=1;i<=length(one);i++)
for (j=1;j<=length(one);j++)
two[one[i] one[j]]
Это создает массив two
с ключами, состоящими из каждой комбинации двух слов в файле.
Второй цикл:
for (i=1;i<=length(one);i++)
if (!(one[i] in two))
print one[i]
Этот цикл выводит каждое слово в файле, которое не отображается как ключ в массиве two
.
Эта версия использует более короткий код и выводит те же слова. Недостатком является то, что не гарантируется, что слова будут в том же порядке, что и во входном файле :
.$ awk '{one[$1]} END{for (w1 in one) for (w2 in one) two[w1 w2]; for (w in one) if (!(w in two)) print w}' file1
gama
zeta
alpha
beta
Для больших файлов описанные выше методы могут привести к переполнению памяти. В этих случаях рассмотрим:
$ sort -u file | awk '{one[$1]} END{for (w1 in one) for (w2 in one) print w1 w2}' >doubles
$ grep -vxFf doubles file
alpha
beta
gama
zeta
Это использует sort -u
для удаления любых повторяющихся слов из файла1, а затем создает файл возможных двойных слов с именем doubles
. Затем grep
используется для печати строк в file
, которых нет в doubles
.
В ОК:
sort file.txt | awk '!pattern || !($0~pattern) { pattern = $0; print }'
Перл:
$ sort file.txt | perl -wnlE 'BEGIN {my $pattern};if(!$pattern || !/$pattern/) {$pattern=$_; say }
С достаточно короткими файлами и при условии, что строки не содержат операторов ERE:
$ LC_ALL=C grep -vxE "($(paste -sd '|' file)){2,}" file
alpha
beta
gama
zeta
Возвращает строки, которые не содержат последовательности из 2 или более строк из file
.
Это работает путем построения команды grep
типа:
LC_ALL=C grep -vxE '(alpha|beta|gama|alphabeta|zeta|gamabeta){2,}' file
Для больших файлов вы столкнетесь с ограничением длины или аргументов+окружения (или одного аргумента в Linux ). Это можно обойти, используя -f -
для передачи регулярного выражения через стандартный ввод, а не через аргументы, но даже в этом случае вы столкнетесь с ограничениями на размер регулярных выражений.
Используя perl
вместо grep
, я могу обрабатывать большие входные данные:
perl -le '
chomp (@words = <>);
$re = "^(". join("|", map {qr{\Q$_\E}} @words). "){2,}\\z";
for (@words) {print unless m/$re/}' file
(, что также позволяет избежать других ограничений, упомянутых выше ).
В любом случае, это займет много времени, так как каждое слово нужно сравнивать с каждым другим словом (, возможно, более одного раза ).
<file awk 'NF {print length "\t" $0}' | sort -k1n,1 | cut -f2- |
awk 'NR==1 {min=length}
(l=length) >= 2*min {
delete k; # clear k array
k[1];
while (length(k))
for (i in k) {
for (j=l-i+1; j>=min; --j)
if (substr($0,i,j) in seen) {
if (i+j-1==l)
next;
k[i+j];
}
delete k[i];
}
}
!seen[$0]++'
Строки, полностью состоящие из ранее просмотренных строк, не будут напечатаны.
Работает путем проверки подстрок на наличие уже просмотренных строк.
Требуется, чтобы входной файл был отсортирован по длине строки от самой короткой до самой длинной. awk | sort | cut
делает это.
Следующая программа awk
начинается с определения длины самой короткой строки (, сохраненной какmin
). Любая строка, длина которой меньше 2*min
, не нуждается в проверке ее подстрок. Вместо этого его можно добавить к хэшу массива seen
и распечатать(!seen[$0]++
используется как условие для печати не -дубликатов, подробнее:Как работает awk '!a[$0]++'?).min
также можно использовать в качестве длины отсечки при проверке подстрок.
При сканировании строк в поисках подстрок необходимо отметить любые новые возможные начальные позиции. Это делается с помощью массива k
для хранения этих смещений. Подстроки сканируются и проверяются, существуют ли они в виде хэша массива seen
. При обнаружении видимой строки:
next
ввода. Строка не печатается и не добавляется в видимый массив. k
и продолжите поиск дополнительных подстрок. while (length(k))
). seen
хеш-массив (и печатается, если она еще не видна ).