Может ли строка «abcedf» соответствовать строке «bafcde» в одной строке?

Я планирую внедрить структуру индексирования в своей программе. Например, если у меня есть 100 строк в таблице, я буду указывать эти строки от 1 до 100 в другом столбце, добавив _ в конец номера ( 1_,2_,3_ etc Чтобы каждый номер можно было идентифицировать однозначно ).

После обработки строк я сохраняю вывод в файл.

Например, я вставляю строку 1_,2_,4_,5_ в файл.

если я получаю значение как 5_,2_,1_,4_ или 2_,5_,1_,4_ , я не должен вставлять эти значения.

Реализация, которая приходит мне на ум, состоит в том, чтобы отсортировать числа и затем сравнить их. Однако, если полные ряды становятся 100 000, это не будет хорошим решением. Возможно ли это как однострочная команда в perl скрипте или awk или sed ?

EDIT :

Чтобы быть более точным и коротким, для набора уникальных и разных значений, как я могу найти все комбинации без повторений?

Пример :

Если у меня есть 3 уникальных ключа 1,2 and 3 , как я могу найти все комбинации без повторения одной и той же комбинации дважды?

Итак, для приведенного выше примера мы можем найти комбинацию,

 123 

Теперь, когда я ищу 213 или 321 он должен дать мне совпадение, поскольку у меня уже есть полученная комбинация 123 .

5 Solutions collect form web for “Может ли строка «abcedf» соответствовать строке «bafcde» в одной строке?”

Вы можете настроить базу данных SQLite и выполнить SQL-выбор из этого, который, вероятно, будет более чистым для реализации, и вы установили, что вы будете более переносимыми позже.

Но вот приблизительная идея. Скажем, у меня есть 2 файла:

 $ more index.txt new_vals.txt :::::::::::::: index.txt :::::::::::::: 1_,2_,4_,5_ :::::::::::::: new_vals.txt :::::::::::::: 5_,2_,1_,4 2_,5_,1_,4 

С помощью этой команды мы можем сопоставить:

 $ for i in $(<new_vals.txt); do nums=${i//_,/}; \ grep -oE "[${nums}_,]+" index.txt; done 1_,2_,4_,5_ 1_,2_,4_,5_ 

Это показывает, что мы можем сопоставить каждую строку с new_vals.txt с существующей строкой в index.txt .

ОБНОВЛЕНИЕ # 1

Основываясь на редактировании OP, следующее будет делать то, что он хочет, используя модификацию вышеупомянутого подхода.

 $ for i in $(<new_vals.txt); do nums=${i//_,/} printf "# to check: [%s]" $i k=$(grep -oE "[${nums}_,]+" index.txt | grep "[[:digit:]]_$") printf " ==> match: [%s]\n" $k done 

С измененной версией тестовых данных:

 $ more index.txt new_vals.txt :::::::::::::: index.txt :::::::::::::: 1_,2_,4_,5_ 0_,2_,3_,9_ :::::::::::::: new_vals.txt :::::::::::::: 5_,2_,1_,4_ 2_,5_,1_,4_ 1_,1_,1_,1_ 1_,2_,4_,4_ 

Теперь, когда мы запускаем выше (в скрипте для простоты, parser.bash ):

 $ ./parser.bash # to check: [5_,2_,1_,4_] ==> match: [1_,2_,4_,5_] # to check: [2_,5_,1_,4_] ==> match: [1_,2_,4_,5_] # to check: [1_,1_,1_,1_] ==> match: [] # to check: [1_,2_,4_,4_] ==> match: [] 

Как это работает

Вышеуказанный метод работает, используя некоторые ключевые характеристики, характерные для характера ваших данных. Например. Только совпадения заканчиваются цифрой, а затем подчеркиванием. grep "[[:digit:]]_$" выбирает только эти результаты.

Другая часть скрипта grep -oE "[${nums}_,]+" index.txt выберет строки, содержащие символы из строк в файле new_vals.txt которые соответствуют строкам из index.txt .

Дополнительные настройки

Если характер данных таков, что строки могут быть переменными по длине, тогда необходимо будет расширить второй grep, чтобы гарантировать, что мы собираем только строки, которые имеют достаточную длину. Существует несколько способов сделать это, либо путем расширения шаблона, либо путем использования счетчика, возможно, используя wc или некоторые другие средства, которые подтвердят, что совпадения имеют определенный тип.

Расширяя его так:

 k=$(grep -oE "[${nums}_,]+" index.txt | \ grep "[[:digit:]]_,[[:digit:]]_,[[:digit:]]_,[[:digit:]]_$") 

Позволит исключить такие строки:

 $ ./parser2.bash # to check: [5_,2_,1_,4_] ==> match: [1_,2_,4_,5_] # to check: [2_,5_,1_,4_] ==> match: [1_,2_,4_,5_] # to check: [1_,1_,1_,1_] ==> match: [] # to check: [1_,2_,4_,4_] ==> match: [] # to check: [1_,2_,5_] ==> match: [] 

Поиск uniques – это кусок пирога с sed :

 { echo identical identical echo not_so_much as_before echo abcdef bafcde } | sed ':u;s/\(.\)\(.*\)\1/\2/;tu' 

ВЫВОД:

 nto_much abfr 

Не совсем уверен, как правильно это представить в Markdown , но вывод из вышеприведенной команды на самом деле является новой строкой и единственным пространством, которое разделяет две строки, затем выше, а затем еще одну новую строку и пробел.

Функция t sed – полностью портативное устройство, определенное POSIX, таким образом:

[ 2addr ] t [ label ] Test.

Вставить в : командный глагол с label если какие-либо подстановки были сделаны с самого последнего чтения строки ввода или выполнения t . Если label не указана, перейдите в конец скрипта.

Давайте посмотрим, как это работает, я добавлю p rint в нужное место:

 { echo identical identical echo not_so_much as_before echo abcdef bafcde } | sed ':u;s/\(.\)\(.*\)\1/\2/p;tu' 

ВЫВОД:

 dentical identcal entical ientcal ntical intcal tical itcal ical ical cal cal al al ll nt_so_much as_befre ntso_much asbefre nto_much abefre nto_much abfr nto_much abfr bcdef bfcde cdef fcde def fde ef fe ff 

Вы можете видеть, что существует различное количество пустого пространства между тремя разными значениями. Это результат порядка, в котором sed отрицает символы, а это означает, что whitespaces также отрицаются, если их четное число.

Команда:

 sed ':u;s/\(.\)\(.*\)\1/\2/;tu' 

s/ выбирает первый символ \(. character \) в строке, которая может быть выбрана \1 дважды, и \(. .все *\) символы между ними. Затем он / заменяет / весь выбор только с выбором \2 между ними. : Промыть, повторить t .

ОПТИМИЗИРУЙТЕ ЭТО!

Мы можем улучшить производительность этой функции с большим размахом, просто добавив в команду только два символа:

 { echo identical identical echo not_so_much as_before echo abcdef bafcde } | sed ':u;s/\(..*\)\(.*\)\1/\2/p;tu' 

ВЫВОД

 nt_so_much as_befre ntso_much asbefre nto_much abefre nto_much abfr nto_much abfr bcdef bfcde cdef fcde ff 

sed теперь выполняет отрицания на любую последовательность из 1 или более символов, которые могут быть дважды выбраны, поэтому идентичность не выглядит в приведенном выше примере – она ​​полностью отрицается на первом проходе.

И без результатов результаты одинаковы:

 { echo identical identical echo about_as_much as_before echo abcdef bafcde } | sed ':u;s/\(..*\)\(.*\)\1/\2/;tu' 

ВЫВОД

 ta_mch fr 

ПОЗИТИВНО ОТ НЕГАТИВНОСТИ

Это требует совсем немного – и не более рекурсии – отрицать отрицание.

 { echo identical identical echo not_so_much as_before echo abcdef bafcde } | sed 'h;:u;s/\(..*\)\(.*\)\1/\2/;tu / ./{H;g; s/^/NOT FULL MATCH:\t/ s/\n/\n\t%:\t/;b} g;s/^/FULL MATCH:\t/' 

ВЫВОД:

 FULL MATCH: identical identical NOT FULL MATCH: not_so_much as_before %: nto_much abfr FULL MATCH: abcdef bafcde 

Или даже просто:

 { echo identical identical echo not_so_much as_before echo abcdef bafcde } | sed -e ':u;s/\(..*\)\(.*\)\1/\2/;tu' \ -e '/ ./{cshite...' -e 'b};cHOORAY!' 

ВЫВОД:

 HOORAY! shite... HOORAY! 

Для концепции с использованием инструментов оболочки sed / grep ExistingSeq = '8_, 1_, 2_, 3_, 4_, 5_, 9_, 7_, 6_'

 NewSeq="5_,2_,1_,4_" # prepa SizeTemp=$( echo "${NewSeq}" | sed -e 's/[^,]//g;s/^/,/' ) Size=${#SizeTemp} echo "${NewSeq}" | sed -e 's/,/\ ,/g;s/^/,/' > /tmp/ToFind # search InsideOcc=$( echo "${ExistingSeq}" | sed -e 's/,/\ ,/g' | egrep -c -f /tmp/ToFind ) # test echo "test with an if on 'InsideOcc' [${InsideOcc}] is lower (not present) or equivalent (present) to Size: [${Size}] " rm /tmp/ToFind 

чтобы быть эффективными и избегать много похожих sed, работать с (временным) индексным файлом с одним элементом на строку.

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

Вот еще один способ: создать «ключ» из строки, отсортировав ее символы:

 gawk ' function generate_key(s, n,a,i,s2) { if (s in cached) return cached[s] n = split(s, a, //) asort(a) for (i=1; i<=n; i++) s2 = s2 a[i] cached[s] = s2 return s2 } { key = generate_key($1) status = (key in seen) ? "no" : "yes" print $1, key, status seen[key]++ } ' OFS="\t" <<END 123 231 321 312 1_,2_,4_,5_ 5_,2_,1_,4_ 2_,5_,1_,4_ END 
 123 123 yes 231 123 no 321 123 no 312 123 no 1_,2_,4_,5_ 1245,,,____ yes 5_,2_,1_,4_ 1245,,,____ no 2_,5_,1_,4_ 1245,,,____ no 

если индексный файл состоит только из строк из 6 символов.
Это будет соответствовать любой комбинации «abcdef» в индексном файле

 grep a indexfile | grep b | grep c | grep d |grep e | grep f 

если индексный файл более сложный, используйте sed для извлечения индексов.

  • Команда оболочки выполняется по-разному в терминале и скрипте
  • Измените определенную строку с помощью sed
  • SED Показывает CRLF, пока Vim не показывает
  • Текст между двумя тегами
  • Обратный grepping
  • Заменить символы в строке соответствия
  • Как удалить все теги HTML с помощью sed?
  • Напишите текст в последней строке документа
  • Преобразование многострочных линий в одну строку с помощью SED
  • вернуть первый экземпляр символов из списка
  • Подготовить строки с префиксом файла с помощью sed или awk
  • Linux и Unix - лучшая ОС в мире.