#bash #sortin& #&rep #data-manipulation
#bash #сортировка #&rep #манипулирование данными
Вопрос:
У меня такая проблема, у меня есть следующие строки:
http://&rouplo&ic.com:80/store/index.cfm?cfid=11812682amp;cftoken=26157811amp;fa=conre
http://&rouplo&ic.com:80/store/index.cfm?fa=PrtSltamp;id=532amp;prTpID=5amp;
http://&rouplo&ic.com:80/store/index.cfm?fa=PrtSltamp;prTpID=5amp;
http://&rouplo&ic.com:80/store/index.cfm?upTp=2amp;fa=up&radeamp;UpNewType=2amp;prTpID=5amp;amp;ptype=FS
http://&rouplo&ic.com:80/store/index.cfm?cfid=11812682amp;cftoken=26157811amp;fa=conreamp;ca=2412
И я хочу удалить каждую строку, содержащую все параметры, из другой строки, скажем, из этих двух строк:
http://&rouplo&ic.com:80/store/index.cfm?cfid=11812682amp;cftoken=26157811amp;fa=conre
http://&rouplo&ic.com:80/store/index.cfm?cfid=11812682amp;cftoken=26157811amp;fa=conreamp;ca=2412
Я хочу сохранить только этот:
http://&rouplo&ic.com:80/store/index.cfm?cfid=11812682amp;cftoken=26157811amp;fa=conreamp;ca=2412
Потому что это тот, у которого больше параметров, и первый был бы избыточным.
Я хотел бы сохранить эти:
http://&rouplo&ic.com:80/store/index.cfm?fa=PrtSltamp;id=532amp;prTpID=5amp;
http://&rouplo&ic.com:80/store/index.cfm?upTp=2amp;fa=up&radeamp;UpNewType=2amp;prTpID=5amp;amp;ptype=FS
http://&rouplo&ic.com:80/store/index.cfm?cfid=11812682amp;cftoken=26157811amp;fa=conreamp;ca=2412
Я хочу удалить каждую строку с одинаковыми параметрами из других строк, сохранить те, у которых больше параметров, а не те, у которых их меньше.
Другой пример:
Я хочу преобразовать это:
http://&rouplo&ic.com:80/Knowled&e/index.cfm?fuseaction=viewamp;docID=111
http://&rouplo&ic.com:80/news-events/index.cfm?fa=viewNewsamp;ID=390
http://&rouplo&ic.com:80/public/quickpoll/index.cfm?fuseaction=quickPollResultsamp;QuestionID=8
http://&rouplo&ic.com:80/store/index.cfm?cfid=11812682amp;cftoken=26157811amp;fa=conre
http://&rouplo&ic.com:80/store/index.cfm?fa=PrtSltamp;id=532amp;prTpID=5amp;
http://&rouplo&ic.com:80/store/index.cfm?upTp=2amp;fa=up&radeamp;UpNewType=2amp;prTpID=5amp;amp;ptype=FS
http://&rouplo&ic.com:80/news-events/index.cfm?fa=viewReleaseamp;ID=21amp;prod=2
http://&rouplo&ic.com:80/content/index.cfm?fuseaction=faq_listamp;ProdID=1amp;archive=1
http://&rouplo&ic.com:80/content/index.cfm?ID=103
http://&rouplo&ic.com:80/Knowled&e/index.cfm?fuseaction=viewamp;amp
http://&rouplo&ic.com:80/knowled&e/index.cfm?fuseaction=viewamp;docID=10
http://&rouplo&ic.com:80/content/index.cfm?ID=123
в это:
http://&rouplo&ic.com:80/Knowled&e/index.cfm?fuseaction=viewamp;docID=111
http://&rouplo&ic.com:80/news-events/index.cfm?fa=viewReleaseamp;ID=21amp;prod=2
http://&rouplo&ic.com:80/public/quickpoll/index.cfm?fuseaction=quickPollResultsamp;QuestionID=8
http://&rouplo&ic.com:80/store/index.cfm?cfid=11812682amp;cftoken=26157811amp;fa=conre
http://&rouplo&ic.com:80/store/index.cfm?fa=PrtSltamp;id=532amp;prTpID=5amp;
http://&rouplo&ic.com:80/store/index.cfm?upTp=2amp;fa=up&radeamp;UpNewType=2amp;prTpID=5amp;amp;ptype=FS
http://&rouplo&ic.com:80/content/index.cfm?fuseaction=faq_listamp;ProdID=1amp;archive=1
http://&rouplo&ic.com:80/content/index.cfm?ID=103
Одни и те же параметры в разных ресурсах, должны быть разными строками.
Если бы я получил это:
http://&rouplo&ic.com:80/content/index.cfm?ID=123
http://&rouplo&ic.com:80/content2/index.cfm?ID=123
Я хочу сохранить их оба.
РЕДАКТИРОВАТЬ 19 августа:
Еще один пример URL-адресов и того, как я хотел бы, чтобы они обрабатывались:
https://es.answers.search.yahoo.com/search?p=mixmail correoamp;fr2=piv-web
https://es.answers.search.yahoo.com/search?p=educastur campusamp;fr2=piv-web
https://techvalidation.dell.com/Default.aspx?id=9d459f5c-8a26-4268-b37c-23980a6ba577amp;Key=/uKb2WS3da4lk/34VSXE4F02YqS5LfvbKFGcDXNQx&IvvbodU3o3lHoNm09M67Utamp;SRC=QuoteCenteramp;newsession=true
https://techvalidation.dell.com/technicalvalidationlist.aspx?key=6ivAYJco9bouAJBNkQ8r&tGWPdfLVRumAScf7bIb6DMpj6SYVdWy6bd4ITEPF4tQMkNzNpGshERZndX3Ia+bqhJ3CnrC46qJkHJ4TdiyN78=amp;PartnerAffinityId=3341728904amp;SRC=QuoteCenter
https://web.xnet.ford.com/3.0/samlerror?faultreason=SSO_LOGOFF
https://web.xnet.ford.com/3.0/samlerror?faultreason=SSO_ERRORamp;lan&ua&e=fr
https://wwwm&.pandacn.ford.com/forms/frmservlet?confi&=pandacn3
https://www.panda.ford.com/forms/frmservlet?confi&=pandain4
https://www.panda.ford.com/forms/frmservlet?confi&=pandain3
Он должен выводить:
https://es.answers.search.yahoo.com/search?p=mixmail correoamp;fr2=piv-web
https://techvalidation.dell.com/Default.aspx?id=9d459f5c-8a26-4268-b37c-23980a6ba577amp;Key=/uKb2WS3da4lk/34VSXE4F02YqS5LfvbKFGcDXNQx&IvvbodU3o3lHoNm09M67Utamp;SRC=QuoteCenteramp;newsession=true
https://techvalidation.dell.com/technicalvalidationlist.aspx?key=6ivAYJco9bouAJBNkQ8r&tGWPdfLVRumAScf7bIb6DMpj6SYVdWy6bd4ITEPF4tQMkNzNpGshERZndX3Ia+bqhJ3CnrC46qJkHJ4TdiyN78=amp;PartnerAffinityId=3341728904amp;SRC=QuoteCenter
https://web.xnet.ford.com/3.0/samlerror?faultreason=SSO_ERRORamp;lan&ua&e=fr
https://wwwm&.pandacn.ford.com/forms/frmservlet?confi&=pandacn3
https://www.panda.ford.com/forms/frmservlet?confi&=pandain4
Мой подход работает только с URL-адресами с одним параметром:
https://www.panda.ford.com/forms/frmservlet?confi&=pandain4
https://www.panda.ford.com/forms/frmservlet?confi&=pandain3
Я делаю: cat list.txt | sort -u -t "=" -k 1,1
и я вывожу:
https://www.panda.ford.com/forms/frmservlet?confi&=pandain4
Но это не удается с этими:
https://web.xnet.ford.com/3.0/samlerror?faultreason=SSO_LOGOFF
https://web.xnet.ford.com/3.0/samlerror?faultreason=SSO_ERRORamp;lan&ua&e=fr
Где я храню
https://web.xnet.ford.com/3.0/samlerror?faultreason=SSO_LOGOFF
с помощью | cat list.txt | sort -u -t "=" -k 1,1
и я хотел именно другую строку
https://web.xnet.ford.com/3.0/samlerror?faultreason=SSO_ERRORamp;lan&ua&e=fr
Потому что он имеет те же параметры и больше.
С уважением!
Комментарии:
1. вы могли бы сделать это в несколько этапов, отсортировать это и рекурсивно сопоставить более короткие в более длинных строках с помощью &rep, добавив несоответствующие последние
2. Почему
http://&rouplo&ic.com:80/news-events/index.cfm?fa=viewNewsamp;ID=390
из первого набора не во втором наборе?3. Вы никогда не отвечаете на этот вопрос. Почему
http://&rouplo&ic.com:80/content/index.cfm?ID=123
в первом наборе, но не во втором? Вам нужно будет уточнить свои критерии.4. Являются ли двойные амперсанды в
http://&rouplo&ic.com:80/store/index.cfm?upTp=2amp;fa=up&radeamp;UpNewType=2amp;prTpID=5amp;amp;ptype=FS
предполагаемыми / обязательными? или амперсанд в КОНЦЕhttp://&rouplo&ic.com:80/store/index.cfm?fa=PrtSltamp;id=532amp;prTpID=5amp;
?5. Подождите — вы хотите сказать, что вам все равно, какие значения были переданы, вам нужно только одно из набора, если все КЛЮЧИ одинаковы???
Ответ №1:
Для правильного выполнения этого требуется много внутренней сортировки, которая внутри bash
цикла порождает множество процессов и слишком сильно замедляет работу.
Переключение на perl
. Обратите внимание, что это изменяет порядок аргументов, а также строк; если вам нужны исходные строки нетронутыми и / или в исходном порядке, нам придется добавить еще один или три шага. Вы также должны отметить, что у вас есть knowled&e
как заглавные, так и строчные буквы; URL-адреса через порт не чувствительны к регистру, но путь после этого чувствителен к регистру, поэтому они не будут регистрироваться как одинаковые, даже если они получат идентичные аргументы.
#!/usr/bin/env perl
use strict; # I ALWAYS use strict and warnin&s unless
use warnin&s; # there is some compellin& reason not to.
open my $fh, 'urls' or die "urls: $!";
my %urlsOUT;
foreach ( <$fh&&t; ) { chomp;
my %ar&s; # clean for each record
m!^(https?://[^/] )(/[^?] )[?](.*)!i; # catch the base in separate case sensitivities
my ($base) = lc($1).$2; # always lowercase the case insensitive part
@ar&s{ split /[?amp;] /, $3 } = (); # removes duplicate ar&s in a url
my ( $ar&s ) = join 'amp;', reverse sort keys %ar&s; # reassemle ORDERED
$urlsOUT{"$base?$ar&s"}=''; # now a unique key
}
my $urlsOUT='';
REC: foreach my $url (reverse sort keys %urlsOUT ) { # ORDERED
for ( split /[?amp;]/, $url ) { # for each ar&
if ( $urlsOUT !~ /b$_b/ ) { # if new
$urlsOUT .= "$urln"; # keep this
next REC; # check next
}
}
}
print $urlsOUT;
Это приведет к последовательному изменению порядка и удалению всех аргументов в URL-адресе, удалению всех результирующих записей, а затем проверит каждую оставшуюся запись (в порядке убывания), чтобы исключить любую запись, в которой нет чего-то, чего раньше не было ни в одной другой записи.
Я назвал программный файл tst
и сделал a tst1
и a urls
.
$: cat tst1
http://test/foo?foo
http://test/foo?bar
http://test/foo?foo
http://test2/foo?foo
http://test2/foo?baz
http://test2/foo?fooamp;bar
http://test2/foo?baz
http://test/foo?fooamp;bar
http://test/foo?baramp;foo
http://test2/foo?baramp;foo
http://test3/foo?bar
http://test3/foo?fooamp;baramp;baz
http://test2/foo?fooamp;baramp;baz
http://test/foo?fooamp;baramp;baz
$: ./tst tst1
http://test3/foo?fooamp;bazamp;bar
http://test2/foo?fooamp;bazamp;bar
http://test/foo?fooamp;bazamp;bar
$: cat urls
http://&rouplo&ic.com:80/Knowled&e/index.cfm?fuseaction=viewamp;docID=111
http://&rouplo&ic.com:80/news-events/index.cfm?fa=viewNewsamp;ID=390
http://&rouplo&ic.com:80/public/quickpoll/index.cfm?fuseaction=quickPollResultsamp;QuestionID=8
http://&rouplo&ic.com:80/store/index.cfm?cfid=11812682amp;cftoken=26157811amp;fa=conre
http://&rouplo&ic.com:80/store/index.cfm?fa=PrtSltamp;id=532amp;prTpID=5amp;
http://&rouplo&ic.com:80/store/index.cfm?upTp=2amp;fa=up&radeamp;UpNewType=2amp;prTpID=5amp;amp;ptype=FS
http://&rouplo&ic.com:80/news-events/index.cfm?fa=viewReleaseamp;ID=21amp;prod=2
http://&rouplo&ic.com:80/content/index.cfm?fuseaction=faq_listamp;ProdID=1amp;archive=1
http://&rouplo&ic.com:80/content/index.cfm?ID=103
http://&rouplo&ic.com:80/Knowled&e/index.cfm?fuseaction=viewamp;amp
http://&rouplo&ic.com:80/knowled&e/index.cfm?fuseaction=viewamp;docID=10
http://&rouplo&ic.com:80/content/index.cfm?ID=123
http://&rouplo&ic.com:80/Knowled&e/index.cfm?fuseaction=viewamp;docID=111
http://&rouplo&ic.com:80/news-events/index.cfm?fa=viewNewsamp;ID=390
http://&rouplo&ic.com:80/public/quickpoll/index.cfm?fuseaction=quickPollResultsamp;QuestionID=8
http://&rouplo&ic.com:80/content/index.cfm?ID=123amp;foo=bar
http://&rouplo&ic.com:80/store/index.cfm?cfid=11812682amp;cftoken=26157811amp;fa=conre
http://&rouplo&ic.com:80/store/index.cfm?fa=PrtSltamp;id=532amp;prTpID=5amp;
http://&rouplo&ic.com:80/store/index.cfm? upTp=2amp;fa=up&radeamp;UpNewType=2amp;prTpID=5amp;amp;ptype=FS
http://&rouplo&ic.com:80/news-events/index.cfm?fa=viewReleaseamp;ID=21amp;prod=2
http://&rouplo&ic.com:80/content/index.cfm?fuseaction=faq_listamp;ProdID=1amp;archive=1
http://&rouplo&ic.com:80/content/index.cfm?ID=103
http://&rouplo&ic.com:80/Knowled&e/index.cfm?fuseaction=viewamp;amp
http://&rouplo&ic.com:80/knowled&e/index.cfm?fuseaction=viewamp;docID=10
http://&rouplo&ic.com:80/content/index.cfm?ID=123
$: ./tst urls
http://&rouplo&ic.com:80/store/index.cfm?upTp=2amp;ptype=FSamp;prTpID=5amp;fa=up&radeamp;UpNewType=2
http://&rouplo&ic.com:80/store/index.cfm?prTpID=5amp;id=532amp;fa=PrtSlt
http://&rouplo&ic.com:80/store/index.cfm?fa=conreamp;cftoken=26157811amp;cfid=11812682
http://&rouplo&ic.com:80/public/quickpoll/index.cfm?fuseaction=quickPollResultsamp;QuestionID=8
http://&rouplo&ic.com:80/news-events/index.cfm?prod=2amp;fa=viewReleaseamp;ID=21
http://&rouplo&ic.com:80/news-events/index.cfm?fa=viewNewsamp;ID=390
http://&rouplo&ic.com:80/knowled&e/index.cfm?fuseaction=viewamp;docID=10
http://&rouplo&ic.com:80/content/index.cfm?fuseaction=faq_listamp;archive=1amp;ProdID=1
http://&rouplo&ic.com:80/content/index.cfm?foo=baramp;ID=123
http://&rouplo&ic.com:80/content/index.cfm?ID=103
http://&rouplo&ic.com:80/Knowled&e/index.cfm?fuseaction=viewamp;docID=111
http://&rouplo&ic.com:80/Knowled&e/index.cfm?fuseaction=viewamp;amp
Обратите внимание, что выходные данные отсортированы с учетом регистра ASCII, с удалением завершающих и повторяющихся / избыточных амперсандов.
Выполнение этого в perl
с помощью внутренних операций чтения и сортировки также намного быстрее.
real 0m0.170s
user 0m0.046s
sys 0m0.092s
старая версия
Я не вижу более элегантного способа, чем двойной проход методом перебора, хотя вы можете, по крайней мере, исключить избыточные сравнения во вложенном цикле.
lst=( $( sort -ru x ) ) # unique reverse sort once to eliminate simple dups
for (( ndx1=0; ndx1<${#lst[@]}-1; ndx1 )) # walk thru once in outer loop
do [[ -n "${lst[ndx1]}" ]] || continue # i&nore removed
for (( ndx2=ndx1 1; ndx2<${#lst[@]}; ndx2 )) # inner skips prev, no redux
do case "${lst[ndx1]}" in # case statement strin& match
"${lst[ndx2]}"*) unset lst[ndx2] ;; # remove shorter versions
*) continue 2 ;; # no match, skip ahead
esac
done
done
printf "%sn" "${lst[@]}" # print out what's left
Я sort
делаю это однозначно в обратном порядке, чтобы исключить простые дублирующие операции и настроить сравнения, а также сохранить в массив для упрощения вложенного цикла.
Внешний цикл обходит массив один раз; он не беспокоится о последней записи, потому что внутренний цикл обработает это. Внутренний цикл начинается с записи после текущей из внешнего цикла — нет причин повторно проверять предыдущие, поскольку они отсортированы.
Поскольку внутренний цикл удалял записи, внешний цикл полностью пропускает проверку, является ли запись внешнего ключа с указанным индексом пустой.
case
Инструкция проверяет каждую запись после текущей из внешнего цикла. Если внутренний ключ содержится в текущей записи ключа внешнего цикла, более короткая версия удаляется из массива с помощью unset
, и цикл переходит к следующей записи, чтобы проверить это.
Когда запись внутреннего цикла больше не является частью ключа внешнего цикла, мы знаем, что пропустили соответствующие записи (поскольку они отсортированы), поэтому мы пропускаем бессмысленную проверку остальной части списка и переходим к следующей записи внешнего ключа с помощью continue 2
.
Это движущееся окно соответствующих записей должно выполнять минимальную работу впустую.
Комментарии:
1. Возможна проблема с чувствительностью к регистру.
2. Я использую вашу программу со списком URL в качестве параметра и получаю те же результаты, я имею в виду, что ни одна строка не удалена = (
3. Это предполагает соответствие регистра и порядка или всех аргументов. Я упускаю что-то важное?
4. Если ваш порядок аргументов меняется, это становится экспоненциально более сложной проблемой.
5. Привет. Аргумент представляет собой список URL-адресов, это может быть любой список URL-адресов, и он должен удалять все строки, содержащие избыточные аргументы, поскольку они есть в других строках с такими же, или одинаковыми и более,.
Ответ №2:
Я вижу следующий алгоритм для этого (к сожалению, я не знаю, как его реализовать):
Сначала вы сортируете свой файл в алфавитном порядке.
Затем вы читаете свой файл построчно, и если строка является подстрокой следующей строки, ее не следует помещать в результирующий файл.
Ответ №3:
Наконец, похоже, я это сделал) для этого тестового файла:
$ cat file2
test?foo
test?bar
test?foo
test2?foo
test2?baz
test2?fooamp;bar
test2?baz
test?fooamp;bar
test?baramp;foo
test2?baramp;foo
test3?bar
test3?fooamp;baramp;baz
test2?fooamp;baramp;baz
test?fooamp;baramp;baz
Скрипт
#!/bin/bash
declare -A resorces
raw=( $(sort -u $1) )
for url in "${raw[@]}"; { resorces[${url//?*}] =" ${url//*?}"; }
for res in "${!resorces[@]}"; {
list=( ${resorces[$res]} )
for i in "${!list[@]}"; {
par=${list[$i]}
unset list[$i]
[[ ${list[@]} =~ $par ]] || result =("$res?$par")
}
}
printf '%sn' "${result[@]}"
Результат
$ ./test2 file2
test2?baramp;foo
test2?fooamp;baramp;baz
test3?fooamp;baramp;baz
test?baramp;foo
test?fooamp;baramp;baz
И для этого тестового файла:
$ cat file
http://&rouplo&ic.com:80/Knowled&e/index.cfm?fuseaction=viewamp;docID=111
http://&rouplo&ic.com:80/news-events/index.cfm?fa=viewNewsamp;ID=390
http://&rouplo&ic.com:80/public/quickpoll/index.cfm?fuseaction=quickPollResultsamp;QuestionID=8
http://&rouplo&ic.com:80/store/index.cfm?cfid=11812682amp;cftoken=26157811amp;fa=conre
http://&rouplo&ic.com:80/store/index.cfm?fa=PrtSltamp;id=532amp;prTpID=5amp;
http://&rouplo&ic.com:80/store/index.cfm?upTp=2amp;fa=up&radeamp;UpNewType=2amp;prTpID=5amp;amp;ptype=FS
http://&rouplo&ic.com:80/news-events/index.cfm?fa=viewReleaseamp;ID=21amp;prod=2
http://&rouplo&ic.com:80/content/index.cfm?fuseaction=faq_listamp;ProdID=1amp;archive=1
http://&rouplo&ic.com:80/content/index.cfm?ID=103
http://&rouplo&ic.com:80/Knowled&e/index.cfm?fuseaction=viewamp;amp
http://&rouplo&ic.com:80/knowled&e/index.cfm?fuseaction=viewamp;docID=10
http://&rouplo&ic.com:80/content/index.cfm?ID=123
http://&rouplo&ic.com:80/content/index.cfm?ID=123
http://&rouplo&ic.com:80/content/index.cfm?ID=123
http://&rouplo&ic.com:80/content/index.cfm?ID=123amp;foo=bar
http://&rouplo&ic.com:80/content/index.cfm?ID=123amp;foo=bar
Результат
$ ./test2 file
http://&rouplo&ic.com:80/content/index.cfm?fuseaction=faq_listamp;ProdID=1amp;archive=1
http://&rouplo&ic.com:80/content/index.cfm?ID=103
http://&rouplo&ic.com:80/content/index.cfm?ID=123amp;foo=bar
http://&rouplo&ic.com:80/public/quickpoll/index.cfm?fuseaction=quickPollResultsamp;QuestionID=8
http://&rouplo&ic.com:80/Knowled&e/index.cfm?fuseaction=viewamp;amp
http://&rouplo&ic.com:80/Knowled&e/index.cfm?fuseaction=viewamp;docID=111
http://&rouplo&ic.com:80/store/index.cfm?cfid=11812682amp;cftoken=26157811amp;fa=conre
http://&rouplo&ic.com:80/store/index.cfm?fa=PrtSltamp;id=532amp;prTpID=5amp;
http://&rouplo&ic.com:80/store/index.cfm?upTp=2amp;fa=up&radeamp;UpNewType=2amp;prTpID=5amp;amp;ptype=FS
http://&rouplo&ic.com:80/knowled&e/index.cfm?fuseaction=viewamp;docID=10
http://&rouplo&ic.com:80/news-events/index.cfm?fa=viewNewsamp;ID=390
http://&rouplo&ic.com:80/news-events/index.cfm?fa=viewReleaseamp;ID=21amp;prod=2
Комментарии:
1. Устраняет дублирующие элементы, но не удаляет меньшие подмножества parms.
2. добавьте
http://&rouplo&ic.com:80/content/index.cfm?ID=103amp;foo=bar
в свой набор данных, он все еще сохраняетсяhttp://&rouplo&ic.com:80/content/index.cfm?ID=103
.3. Я протестировал это, и, похоже, это не удаляет ни одной строки: snipboard.io/lbHJQS.jp&
4. В вашем файле изменяется порядок аргументов. Я не рассматривал вопрос о переупорядочении. Мы можем , но это добавляет больше логики, и я не видел никаких обращений или переупорядочивания в списке примеров (я пропустил это?)
5. Да, но я считаю это другим набором опций