regex - utilizar - Bash, grep entre dos líneas con una cadena especificada
grep expresiones regulares (8)
Ejemplo:
a43
test1
abc
cvb
bnm
test2
kfo
Necesito todas las líneas entre test1 y test2. Grep normal no funciona en este caso. ¿Tienes alguna proposición?
Ella es un poco awk
Estas se imprimirán de test1
a test2
awk ''/test1/{f=1} /test2/{f=0;print} f''
awk ''/test1/{f=1} f; /test2/{f=0}''
awk ''/test1/,/test2/''
test1
abc
cvb
bnm
test2
Estos imprimen datos entre test1
a test2
awk ''/test1/{f=1;next} /test2/{f=0} f''
awk ''/test2/{f=0} f; /test1/{f=1}''
abc
cvb
bnm
Puedes usar sed
:
sed -n ''/test1/,/test2/p'' filename
Para excluir las líneas que contienen test1
y test2
, diga:
sed -n ''/test1/,/test2/{/test1/b;/test2/b;p}'' filename
Si solo puedes usar grep:
grep -A100000 test1 file.txt | grep -B100000 test2 > new.txt
grep -A
y luego un número obtiene las líneas después de la cadena correspondiente, y grep -B
obtiene las líneas antes de la cadena correspondiente. El número, 100000 en este caso, debe ser lo suficientemente grande como para incluir todas las líneas antes y después.
Si no desea incluir test1 y test2, puede eliminarlos luego mediante grep -v
, que imprime todo excepto la (s) línea (s) correspondiente (s):
egrep -v "test1|test2" new.txt > newer.txt
o todo en una línea:
grep -A100000 test1 file.txt | grep -B100000 test2 | egrep -v "test1|test2" > new.txt
awk ''/test1/,/test2/'' filename.txt > outputFile.txt
Sí, grep normal no hará esto. Pero grep con el parámetro -P
hará este trabajo.
$ grep -ozP ''(?s)test1/n/K.*?(?=/ntest2)'' file
abc
cvb
bnm
/K
descarta que los caracteres previamente coincidentes se (?=/ntest2)
en la final y el aspecto positivo hacia (?=/ntest2)
afirma que la coincidencia debe ir seguida de un /n
carácter de nueva línea y luego una cadena de test2
.
Usted puede hacer algo como esto también. Permite decir que este archivo test.txt
con contenido:
a43
test1
abc
cvb
bnm
test2
kfo
Tu puedes hacer
cat test.txt | grep -A10 test1 | grep -B10 test2
donde -A<n>
es para obtener n
líneas después de su coincidencia en el archivo y -B<n>
es para darle n
líneas antes de la coincidencia. Solo tiene que asegurarse de que n > number of expected lines between test1 and test2
. O puede darlelo lo suficientemente grande como para llegar a EOF.
Resultado:
test1
abc
cvb
bnm
test2
La respuesta de PratPor arriba:
cat test.txt | grep -A10 test1 | grep -B10 test2
es genial ... pero si no sabes la longitud del archivo:
cat test.txt | grep -A1000 test1 | grep -B1000 test2
No es determinista, pero no está mal. ¿Alguien tiene mejor (más determinista)?
La siguiente secuencia de comandos finaliza este proceso. Más detalles en esta publicación similar de
get_text.sh
function show_help()
{
HELP=$(doMain $0 HELP)
echo "$HELP"
exit;
}
function doMain()
{
if [ "$1" == "help" ]
then
show_help
fi
if [ -z "$1" ]
then
show_help
fi
if [ -z "$2" ]
then
show_help
fi
FILENAME=$1
if [ ! -f $FILENAME ]; then
echo "File not found: $FILENAME"
exit;
fi
if [ -z "$3" ]
then
START_TAG=$2_START
END_TAG=$2_END
else
START_TAG=$2
END_TAG=$3
fi
CMD="cat $FILENAME | awk ''/$START_TAG/{f=1;next} /$END_TAG/{f=0} f''"
eval $CMD
}
function help_txt()
{
HELP_START
get_text.sh: extracts lines in a file between two tags
usage: FILENAME {TAG_PREFIX|START_TAG} {END_TAG}
examples:
get_text.sh 1.txt AA => extracts lines in file 1.txt between AA_START and AA_END
get_text.sh 1.txt AA BB => extracts lines in file 1.txt between AA and BB
HELP_END
}
doMain $*