Espero que haja algum caractere - ou pelo menos alguma string -
que nunca aparece no seu arquivo.
Eu assumirei que isso é verdade para | .
Para ser mais seguro, usarei || .
Execute este comando:
sed -n -e H -e '/^ *\/> *$/ { s/.*//; x; s/.*NS1:name="\([^"]*\)/&/; s/\n/||/gp }' your_file \
| sort \
| nl -ba \
| sed -e 's/ *\([0-9]*\)[^|]*||\(.* RDF:about="rdf:#$CHROME\)[0-9]*//' -e 's/||/\n/g'
Nota: Isso (provavelmente) requer que você tenha o GNU sed.
Visão geral
- Use
sedpara transformar o arquivo em um formato adequado para classificação (detalhes abaixo). - Classifique a saída de
sed. - Aplicar números de linha (pré-anexados).
Use qualquer comando que gere números adequados.
Eu gosto de
nl -ba, mascat -nfuncionaria tão bem, e provavelmente há outras opções. - Use
sedpara remover o número da linha desde o começo da linha e insira-o apósCHROME. Desprenda os dados de volta para o formato original.
Detalhes - Primeiro sed de comando
O comando sort trata cada linha como um registro.
Portanto, pegamos cada registro (delimitado) do seu arquivo de entrada
e concatenar todas as linhas, formando uma linha longa.
Também copiamos o valor name para o início da linha,
para evitar ter que especificar uma chave de classificação.
- Use a opção
-npara suprimir a impressão automática. As linhas serão impressas apenas quando dissermosp. -
Execute
Hem todas as linhas. Isso acrescenta a linha atual ao espaço de espera. Logicamente, isso pode fazer mais sentido para copiar a linha<para o espaço de espera (com o comandoh) e, em seguida, anexe todas as linhas subsequentes. Eu arbitrariamente escolhi essa abordagem.Observe que, como adicionamos a linha
<a um espaço vazio, o registro agregado tem uma nova linha extra no começo. - Procure uma linha contendo
/>, opcionalmente precedido e / ou seguido por espaços. Quando a encontramos, sabemos que temos um registro completo no espaço de espera. Faça os seguintes comandos apenas nessas linhas.-
s/.*//limpa o espaço do padrão (isto é, apaga a linha/>). Isso não está realmente jogando fora qualquer informação; a linha/>já foi anexada ao espaço de espera (porque toda a linha é anexada ao espaço de espera). -
xtroca o espaço de padrões e o espaço de armazenamento. Isso recupera o registro agregado (anexado / concatenado) do espaço de espera no espaço padrão. Por causa do comando anterior (s/.*//), isso limpa o espaço de espera. -
s/.*NS1:name="\([^"]*\)/&/procura o campo de nome e copia seu valor para o início do registro. Isso falhará se você puder ter um nome com caracteres de citação nele. -
s/\n/||/gpsubstitui cada nova linha no espaço padrão com||. (Esta é a etapa que converte o registro em uma linha). Por causa dop, isso imprime o registro.
-
A saída do primeiro comando sed , quando executada em seu arquivo de amostra, é
AAA Carolinas||<RDF:Description RDF:about="rdf:#$CHROME1"|| NS1:name="AAA Carolinas"|| NS1:urlToUse=""|| NS1:whereLeetLB="off"|| NS1:leetLevelLB="1"|| NS1:hashAlgorithmLB="md5"|| NS1:passwordLength="16"|| NS1:usernameTB="user"|| NS1:counter=""|| NS1:charset="a9b0c8d1e7f2g6h3i5j4klmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV123456789"|| NS1:prefix="6%Fl"|| NS1:suffix="I$5g"|| NS1:protocolCB="false"|| NS1:subdomainCB="true"|| NS1:domainCB="true"|| NS1:pathCB="false"|| />
Adobe Forums||<RDF:Description RDF:about="rdf:#$CHROME2"|| NS1:name="Adobe Forums"|| NS1:urlToUse="adobeforums.com"|| NS1:whereLeetLB="off"|| NS1:leetLevelLB="1"|| NS1:hashAlgorithmLB="md5"|| NS1:passwordLength="12"|| NS1:usernameTB="username"|| NS1:counter=""|| NS1:charset="a9b0c8d1e7f2g6h3i5j4klmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV"|| NS1:prefix=""|| NS1:suffix=""|| NS1:protocolCB="false"|| NS1:subdomainCB="true"|| NS1:domainCB="true"|| NS1:pathCB="false"|| NS1:pattern0="*adobeforums.com*"|| NS1:patternenabled0="true"|| NS1:patterndesc0=""|| NS1:patterntype0="wildcard"|| />
Adorama||<RDF:Description RDF:about="rdf:#$CHROME3"|| NS1:name="Adorama"|| NS1:urlToUse="adorama.com"|| NS1:whereLeetLB="off"|| NS1:leetLevelLB="1"|| NS1:hashAlgorithmLB="md5"|| NS1:passwordLength="8"|| NS1:usernameTB="username"|| NS1:counter=""|| NS1:charset="a9b0c8d1e7f2g6h3i5j4klmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV"|| NS1:prefix=""|| NS1:suffix=""|| NS1:protocolCB="false"|| NS1:subdomainCB="false"|| NS1:domainCB="true"|| NS1:pathCB="false"|| NS1:pattern0="*adorama.com*"|| NS1:patternenabled0="true"|| NS1:patterndesc0=""|| NS1:patterntype0="wildcard"|| NS1:pattern1="www.adoramapix.com*"|| NS1:patternenabled1="true"|| NS1:patterndesc1=""|| NS1:patterntype1="wildcard"|| />
Detalhes - Segundo sed comando
-
s/ *\([0-9]*\)[^|]*||\(.* RDF:about="rdf:#$CHROME\)[0-9]*//divide a linha em pedaços:- Zero ou mais espaços.
- O número da linha (zero ou mais dígitos).
Isso se torna o grupo
. - A guia após o número da linha, o valor
namee o||após ele. - O registro foi feito em
RDF:about="rdf:#$CHROME. Isso se torna o grupo. - O número do registro antigo (zero ou mais dígitos).
- Implicitamente, o resto do registro.
Em seguida, substitui as cinco primeiras peças com
RDF:about="rdf:#$CHROMEe o número da linha (o novo número de registro). Como o resto do registro não foi correspondido, não é afetado pelo comando. -
s/||/\n/gsubstitui cada||por uma nova linha, restaurar (recriar) a estrutura original de várias linhas do arquivo.
Obviamente,…
... para enviar a saída para um arquivo,
adicione > your_output_file no final
da última linha do comando (ou seja, no final do segundo sed ).
Você pode então mover ( mv ) your_output_file para o seu arquivo original.
Não faz sentido algum especificar a opção --output= (ou -o )
para o comando sort ;
a saída de sort deve entrar no comando
que aplica os números de linha.
Se você quiser capturar um arquivo intermediário, diga isso.