Витягніть слово з рядка за допомогою grep / sed / awk


12

У мене струна

00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256

і хочуть витягти слово, qaяке випливає далі -Dspring.profiles.active.

У мене є рядок збереження у файлі text.txt просто для демонстрації на ньому.

Коли я це роблю

grep -r -o "spring.profiles.active=" text.txt

Результат - spring.profiles.active=

Це слово не завжди є qa, могло бути prodабо dev.

Те , що я хотів би зробити , це знайти слово spring.profiles.activeі після того, як в =екстракті цього слова.

Я хотів би описати цей сценарій, тому що я використовую слово для налаштування інших елементів на сервері.

Чи можливо це, і якщо так, то як це зробити?


Я здогадуюсь, про це вже були мета-розмови, але це питання зовсім не специфічне для Ubuntu. Чому він тут замість unix.stackexchange.com ?
Тоні Адамс

@TonyAdams Так там є: обробка текстів питання були побічно покриті тут , і у всякому разі де-факто вони завжди розглядаються в темі і не закриті / мігрували; про специфіку Ubuntu, яку висвітлювали неодноразово, двічі зовсім недавно тут, у двох примірниках та один раз тут .
kos

Хороше питання! : D
ncomputers

Відповіді:


20

Ви можете використовувати grepз PCRE ( -P):

grep -Po 'spring.profiles.active=\K[^ ]+' <<<'.....string.....'
  • spring.profiles.active=відповідатиме цій підрядці буквально, \Kвідкине збіг

  • [^ ]+вибере потрібну частину, тобто частину після spring.profiles.active=, до наступного пробілу

Для файлу:

grep -Po 'spring.profiles.active=\K[^ ]+' file.txt

Приклад:

% grep -Po 'spring.profiles.active=\K[^ ]+' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256'
qa

sed подібна логіка:

sed -r 's/.*spring.profiles.active=([^ ]+).*/\1/' <<<'.....string.....'

Приклад:

% sed -r 's/.*spring.profiles.active=([^ ]+).*/\1/' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256'
qa

Помилки обробки:

У вашому сценарії ви можете обробити той випадок, коли немає відповідності, іншими словами, коли ваша початкова рядок не містить spring.profiles.active=. У наведеному вище sedприкладі ви отримуєте всю початкову рядок, яка може створити проблеми:

% var="$(sed -r 's/.*spring.profiles.active=([^ ]+).*/\1/' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -XX:MaxPermSize=256')"
% echo $var
00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -XX:MaxPermSize=256

Якщо ви віддаєте перевагу отримати порожній рядок, коли немає відповідності, додайте -nпараметр до sedкоманди та pпараметр до sed sкоманди, як це:

% var="$(sed -rn 's/.*spring.profiles.active=([^ ]+).*/\1/p' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -XX:MaxPermSize=256')"
% echo $var

% var="$(sed -rn 's/.*spring.profiles.active=([^ ]+).*/\1/p' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256')"
% echo $var
qa

Тоді ви можете перевірити, чи $ var порожній чи ні.


Дякую @heemay, працює чудово. тепер мені просто потрібно це сценарій. Я
відзначу

@heemay, ти знаєш, як я можу це зробити? У мене це є в сценарії, і коли він працює, повертаю qa. Я хочу зберегти результат у змінній під назвою env, а потім порівняти її з чимось подібним. Якщо [env == qa]; тоді // Зробіть щось ... ще щось зробіть ...
Gman

1
@Gman Так .. просто використовуйте заміну команд: var="$(grep -Po 'spring.profiles.active=\K[^ ]+' file.txt)"замініть file.txtна, <<<'...string...'якщо введення - це рядок, а не файл ... тоді ви можете зробитиif [ "$var" = 'qa' ]; then do something; else do something; fi
heemayl

1

Використання awk

awk -F"-Dspring.profiles.active=" '{sub(/ .*/,"",$2);print $2}' <<<'your_string'

або

awk -F"-Dspring.profiles.active=" '{sub(/ .*/,"",$2);print $2}' your_file

Приклад

% awk -F"-Dspring.profiles.active=" '{sub(/ .*/,"",$2);print $2}' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256'
qa

1

Я кину Perl у суміш:

<<<'string' perl -lane '$F[3]=~s/.*?=//;print($F[3])'
  • -l: дозволяє автоматичну обробку ліній. Він має два окремих ефекту. По-перше, він автоматично підключає $ / (роздільник вхідних записів) при використанні з -n або -p. По-друге, він призначає $ \ (розділювач записів вихідних даних) мати значення octnum, щоб будь-які оператори друку знову додавали цей роздільник. Якщо octnum опущено, встановлює $ \ поточне значення $ /.
  • -a: увімкнює режим автошпліту при використанні з -n або -p. Неявна розділена команда для масиву @F виконується як перше, що знаходиться всередині неявного циклу в той час, як цикл виробляється -n або -p.
  • n: змушує Perl взяти на себе наступний цикл навколо вашої програми, що змушує ітерацію аргументів імені файлу дещо нагадувати sed -n або awk:

    LINE:
      while (<>) {
          ...             # your program goes here
      }
    
  • -e: може використовуватися для введення одного рядка програми.
% <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256' perl -lane '$F[3]=~s/.*?=//;print($F[3])'
qa

Оригінальний регекс можна використовувати також так:perl -nle '/spring.profiles.active=\K([^ ]+)/ && print $1' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256'
Манве
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.