Пример:
a43
test1
abc
cvb
bnm
test2
kfo
Мне нужны все строки между test1 и test2. В этом случае нормальный grep не работает. Есть ли у вас какие-либо предложения?
Пример:
a43
test1
abc
cvb
bnm
test2
kfo
Мне нужны все строки между test1 и test2. В этом случае нормальный grep не работает. Есть ли у вас какие-либо предложения?
Печать от
test1
доtest2
(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
Печатает данные между
test1
totest2
(исключая строки запуска)
awk '/test1/{f=1;next} /test2/{f=0} f'
awk '/test2/{f=0} f; /test1/{f=1}'
abc
cvb
bnm
Вы можете использовать sed
:
sed -n '/test1/,/test2/p' filename
Чтобы исключить строки, содержащие test1
и test2
, скажем:
sed -n '/test1/,/test2/{/test1/b;/test2/b;p}' filename
Если вы можете использовать grep:
grep -A100000 test1 file.txt | grep -B100000 test2 > new.txt
grep -A
, а затем число получает строки после строки соответствия, а grep -B
получает строки перед соответствующей строкой. Число, 100000 в этом случае, должно быть достаточно большим, чтобы включать все строки до и после.
Если вы не хотите включать test1 и test2, вы можете впоследствии удалить их с помощью grep -v
, который печатает все, кроме соответствующих строк:
egrep -v "test1|test2" new.txt > newer.txt
или все в одной строке:
grep -A100000 test1 file.txt | grep -B100000 test2 | egrep -v "test1|test2" > new.txt
Да, нормальный grep этого не сделает. Но grep с параметром -P
выполнит эту работу.
$ grep -ozP '(?s)test1\n\K.*?(?=\ntest2)' file
abc
cvb
bnm
\K
отбрасывает ранее согласованные символы от печати в финале, а положительный lookahead (?=\ntest2)
утверждает, что за совпадением должен следовать символ \n
новой строки, а затем строка test2
.
Следующий script завершает этот процесс. Подробнее fooobar.com/questions/28804/...
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 $*
Вы тоже можете сделать что-то подобное. Допустим, вы этот файл test.txt
с контентом:
a43
test1
abc
cvb
bnm
test2
kfo
Вы можете сделать
cat test.txt | grep -A10 test1 | grep -B10 test2
где -A<n>
должно вывести строки n
после вашего совпадения в файле, а -B<n>
- дать вам строки n
перед совпадением. Вы просто должны убедиться, что n > number of expected lines between test1 and test2
. Или вы можете дать ему достаточно большой, чтобы достичь EOF.
Результат:
test1
abc
cvb
bnm
test2
Ответ от PratPor выше:
cat test.txt | grep -A10 test1 | grep -B10 test2
классно.. но если вы не знаете длину файла:
cat test.txt | grep -A1000 test1 | grep -B1000 test2
Не детерминированный, но не слишком плохой. Кто-нибудь лучше (более детерминированный)?
awk '/test1/,/test2/' filename.txt > outputFile.txt