Обработка текста - Как получить строку соответствия шаблону A до первого появления строки соответствия шаблону B?

Ответ Жиля верен в том, что версия команды find для Windows предшествует версии cygwin, и поэтому она вызывается.

Однако использование Cygwin будет означать, что любые командные файлы, использующие команду windows find , теперь фактически будут вызывать команду cygwin find , что может быть не тем, что вам нужно.

На мой взгляд, наиболее симбиотическим способом работы обоих является выполнение следующих действий:

  1. Найдите команду cygwin find и переименуйте / скопируйте ее в lfind.exe (или любое другое имя, не указанное в PATH Windows)
  2. В вашем файле ~ / .bashrc добавьте строку alias find = lfind

Таким образом , когда вы запускаете find из терминала cygwin, вы будете использовать версию cygwin, но командные файлы будут использовать версию Windows.

Примечание: вам все равно понадобится каталог bin cygwin в вашем PATH, но теперь он может быть дальше от системного каталога Windows.

1
09.02.2018, 04:19
2 ответа

Leyendo nuevamente su descripción, entiendo que desea la primera coincidencia del patrón B de abajo hacia arriba hasta (subiendo )la primera coincidencia del patrón A. Pero las secciones resultantes deben estar en el orden en que el archivo posee.

Eso requiere mucha lógica. El siguiente script shell lo hace todo. Colocará los resultados en el orden interno correcto en los archivos Ey algún número, el primer archivo(E1)tendrá la primera coincidencia desde arriba, el último archivo tendrá la sección de la última coincidencia.

#!/bin/bash

rm -rf resE* E*

tac../example_file.txt |
    awk 'BEGIN{i=1}
         /^AK5\*R.*/{p=1}
         {if(p==1){f="resE" i;print($0)>>f;close(f)}}
         /^AK2.*/{if(p==1){i++};p=0}
        '
set -- resE* 
c=$#
for (( i=1;i<=$c;i++)); do
    pos=$(($c-$i+1))
    [ -f "$1" ] && tac "$1" > "E$pos"
    shift
done

Los rangos resultantes serán:

$ cat E1
AK2*777*7777777
AK3*S6*5**3
AK3*A2*5**3
AK4*3*6969*4
AK4*7*6969*4
AK5*R*5

$ cat E2
AK2*777*7777777
AK3*J7*5**3
AK4*3*6969*4
AK5*R*5
1
27.01.2020, 23:32

POSIXexal rescate otra vez!

exes el editor de archivos programable especificado por POSIX -. Para cualquier cosa que implique direccionamiento hacia atrás, suele ser una solución mucho mejor que Awk o Sed.

El siguiente delineador -funciona perfectamente en tuexample_file2.txt:

printf '%s\n' 'g/AK5[*]R/?AK2?,.p' | ex example_file.txt

En su example_file.txt, también funciona, pero debido a que el comando lobal gen exno puede escribir en un destino separado para cada rango sobre el que se actúa, los dos archivos de salida deseados se fusionan así:

AK2*777*7777777
AK3*S6*5**3
AK3*A2*5**3
AK4*3*6969*4
AK4*7*6969*4
AK5*R*5
AK2*777*69696969
AK3*J7*5**3
AK4*3*6969*4
AK5*R*5

Sin embargo, esto es bastante fácil de manejar con otra herramienta POSIX, csplit, que está diseñada para dividir archivos según un "contexto".

Solución POSIX portátil:

patA='AK5[*]R'
patB='AK2'

printf '%s\n' "g/$patA/?$patB?,.p" |
  ex example_file.txt |
  csplit -f my_unique_prefix_ -n 1 -s -k - "/$patB/" '{999}'

for f in my_unique_prefix_*; do
  mv "$f" "e${f##my_unique_prefix_}.txt";
done

rm e0.txt

Hay un elemento final para que esta sea una solución perfecta, que es volver a numerar los archivos en orden inverso. No he hecho esta parte.


Si no le importa que la numeración de los archivos esté en el mismo orden que el archivo, y si no le importa si se omite la extensión .txt, y si no le importa si los archivos están numerados desde e01en lugar de desde e1, y si no le importa que se imprima un mensaje de diagnóstico sobre cuántas líneas se colocaron en cada archivo, entonces podemos simplificar:

patA='AK5[*]R'
patB='AK2'

printf '%s\n' "g/$patA/?$patB?,.p" |
  ex example_file.txt |
  csplit -f e -k - "/$patB/" '{999}'

rm e00
1
27.01.2020, 23:32

Теги

Похожие вопросы