Как напечатать строку между двумя символами с помощью команды Linux/bash

Я пытаюсь найти команду Linux, которая могла бы дать мне текст между [ и ]. Я пробовал стандартные grep и sed, но пока ничего не помогло. Скажем, текст находится в LOGS. нравиться -

    Starting mongo client..
Connecting to truststore.pki.rds.amazonaws.com (99.84.66.9:443)
global-bundle.pem    100% |********************************|  183k  0:00:00 ETA
MongoDB shell version v4.0.6
connecting to: mongodb://XXXx.amazonaws.com:27017/?authSource=XXX&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("XXXXXXX") }
MongoDB server version: 5.0.0
WARNING: shell and server versions do not match
----------------------------------------------------------------------------------------------------
        Listing Existing set of collections
----------------------------------------------------------------------------------------------------
[
    "10w",
    "11w",
    "Test1",
    "Test2",
    "QA_Testing",
    "QueuesTest",
    "TestPagination",
]

Мне нужен был текст только с именами этой коллекции внутри []

Пробовал до сих пор

  1. echo "$LOGS" | grep -o "\[.*\]"
  2. echo "$LOGS" | sed -n 's/.*\[\([^]]*\)\].*/\1/p'
  3. echo "$LOGS" | grep -o '\[\K[^\]]+'
  4. echo "$LOGS" | awk -F'[][]' '{for(i=2;i<=NF;i+=2) print $i}'

Никто из них пока не помог. Они не показывают никаких ошибок, но и никакого вывода. Может ли кто-нибудь помочь с правильной командой, которая может мне помочь?

Что делать, если скобки появляются внутри скобок? Что, если они не придут парами?

pmf 06.09.2024 13:18

первый (echo | grep) у меня работает; 2-й и 4-й почти работают, за исключением того, что литеральные [ и ] удаляются (довольно легко убедиться, что они добавлены обратно); пожалуйста, обновите вопрос, указав полный вывод для каждой из ваших 4 попыток кодирования

markp-fuso 06.09.2024 15:00

4-я попытка предназначена для анализа нескольких наборов [] из одной строки ввода; может ли ваш ввод включать несколько пар []? если «да», то укажите это в вопросе (и желательно покажите пример ввода и ожидаемый результат)

markp-fuso 06.09.2024 15:02

@EdMorton: эти команды не дали никакого результата. Извините, я пропустил это упомянуть

RCode 06.09.2024 15:04

Покажите желаемый результат для этого примера ввода в вашем вопросе (без комментариев).

Cyrus 06.09.2024 15:46

Ваше недавнее редактирование превратило этот вопрос в совершенно другой вопрос, чем тот, который вы изначально задали, с лучшим возможным решением, чем предлагаемые регулярные выражения. Вам следует вернуть этот вопрос в том виде, в котором вы его задали, а затем задать новый вопрос о анализе этого совершенно другого формата ввода (и добавить точный ожидаемый результат), иначе все, кто пытался вам помочь, просто тратили свое время.

Ed Morton 06.09.2024 17:46
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
83
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

$ echo "$logs" | grep -o '\[.*]'
[apple, pineapple, wood-apple]

$ echo "$logs" | sed -n 's/.*\(\[.*]\).*/\1/p'
[apple, pineapple, wood-apple]

$ echo "$logs" | awk -F'[][]' '{print "[" $2 "]"}'
[apple, pineapple, wood-apple]

$ echo "$logs" | awk 'match($0,/\[.*]/){print substr($0,RSTART,RLENGTH)}'
[apple, pineapple, wood-apple]

$ echo "$logs" | gawk 'match($0,/\[.*]/,a){print a[0]}'
[apple, pineapple, wood-apple]

$ echo "$logs" | gawk '{print gensub(/.*(\[.*]).*/, "\\1", 1)}'
[apple, pineapple, wood-apple]

$ [[ "$logs" =~ \[.*] ]] && echo "${BASH_REMATCH[0]}"
[apple, pineapple, wood-apple]

Для команды grep требуется расширение -o, отличное от POSIX, предоставляемое GNU grep, последние две команды awk требуют GNU awk для не-POSIX расширений gensub() и третьего аргумента match(). Все остальное будет работать в любой версии инструментов, но, поскольку вы используете Linux, у вас, вероятно, все равно есть инструменты GNU.

Вышеупомянутое будет делать то, что вы просили, учитывая одну пару совпадающих [...] в строке, как показано в вашем вопросе, но делать разные вещи для несовпадающих, множественных, вложенных и/или перекрывающихся пар [...] в строке - если у вас есть такие об этих ситуациях и не можете решить эту проблему самостоятельно, тогда задайте новый вопрос об этом, показывающий, как вы хотели бы, чтобы эти случаи рассматривались.

Я использую logs вместо LOGS по причинам, описанным в Правильная заглавная буква переменных Bash и сценария оболочки.

Привет @Эд Мортон, спасибо за подробный отчет. Спасибо и за ваше время. Я думаю, что в моем случае они не выдают никакого вывода, так как между ними выглядят символы новой строки. Я обновил описание, добавив более конкретное описание к моему сценарию. Можете ли вы проверить один раз и помочь?

RCode 06.09.2024 15:15

Вы можете извлечь строки между скобками, а затем упорядочить их после того, как они у вас появятся. Например;

  • Используя awk:

    echo "$logs" | awk -F'[][]' '{print $2}'

  • Используя sed:

    echo "$logs" | sed -n 's/.*\[\([^]]*\)\].*/\1/p'

  • Используя grep -oP:

    echo "$logs" | grep -oP '(?<=\[)[^]]*(?=\])'

Вернут только «яблоко, ананас, лесное яблоко». Если это необходимо, вы можете добавить/объединить/добавить скобки после их получения.


Изменить. Основываясь на изменениях редактирования и комментариев автора, я добавил новое решение следующим образом.

Ваш ввод $logs может быть обработан, например:

  • Используя awk:

echo $logs | awk '/\[/{flag=1; next} /\]/{flag=0} flag {printf "%s", $0}'

/\[/{flag=1; next} этот раздел устанавливает флаг, когда встречается [. /\]/{flag=0} этот раздел сбрасывает флаг при обнаружении ]. Последняя часть печатает строки, пока установлен флаг, эффективно объединяя многострочный ввод.

  • Используя sed:

echo $logs | sed -n '/\[/,/\]/p' | sed ':a;N;$!ba;s/\n//g' | sed 's/.*\[\(.*\)\].*/\1/'

Вам придется использовать sed несколько раз. Сначала находят строки между [ и ]. Второй объединяет все строки вместе, а последний извлекает содержимое между [ и ].

  • Используя grep и tr:

echo $logs | grep -oP '(?<=\[)[\s\S]*(?=\])' | tr -d '\n'

Раздел grep соответствует всем символам между [ и ] (включая символы новой строки), а раздел tr удаляет символы новой строки, чтобы создать одну строку.

Спасибо за ваше время. Я думаю, что в моем случае они не выдают никакого вывода, так как между ними выглядят символы новой строки. Я обновил описание, добавив более конкретное описание к моему сценарию. Можете ли вы проверить один раз и помочь?

RCode 06.09.2024 15:16

обновил мой ответ на основе вашего изменения вопроса. надеюсь, это поможет!

burcu 06.09.2024 15:44
echo $logs будет делать разные вещи в зависимости от версии echo, содержимого logs, каталога, из которого вы его запускаете, настроек переменных среды и т. д. Всегда заключайте переменные в кавычки, см. mywiki.wooledge.org/Quotes. Кроме того, tr -d '\n' превращает входные данные в выходные данные, которые больше не являются допустимым текстовым «файлом» POSIX, и поэтому любой последующий вызов инструмента обработки текста, такого как grep, sed или awk, делает с этим неопределенное поведение. Это почти никогда не лучший подход к чему-либо.
Ed Morton 06.09.2024 17:54

Одна из вещей, которую echo $logs БУДЕТ сделать, — это превратить все пробелы, включая символы новой строки, в одиночные пустые символы, чтобы последующая передача этого в ваш awk-скрипт с использованием переменной-флага не работала.

Ed Morton 06.09.2024 17:55

Спасибо большое @burcu. Это помогло

RCode 06.09.2024 22:10

По крайней мере, для вашего значения LOGS (вы не указали общий формат текста) в bash должно работать следующее:

LOGS='[apple, pineapple, wood-apple]'
echo ${LOGS//[][]/}

// вызывает удаление всех вхождений шаблона. Шаблон представляет собой шаблон подстановочного знака (т. е. glob), в данном случае класс символов [ ... ], содержащий два символа ][.

Я использовал ответ, предоставленный бурку, но tr перед тем, как перейти к grep:

echo "$logs" | tr -d '\n' | grep -oP '(?<=\[)[\s\S]*(?=\])'

В моем случае сработало.

echo $logs будет делать разные вещи в зависимости от версии echo, содержимого logs, каталога, из которого вы его запускаете, настроек переменных среды и т. д. Всегда заключайте переменные в кавычки, см. mywiki.wooledge.org/Quotes. Кроме того, tr -d '\n' превращает входные данные в выходные данные, которые больше не являются допустимым текстовым «файлом» POSIX, и поэтому любой последующий вызов инструмента обработки текста, такого как grep, sed или awk, делает с этим неопределенное поведение. Это почти никогда не лучший подход к чему-либо.
Ed Morton 06.09.2024 17:52

В любом случае tr -d '\n' не делает ничего полезного, поскольку echo $logs уже преобразует все символы новой строки в пробелы, так что tr удаляет только новую строку с конца строки (т. е. искажает ввод в grep).

Ed Morton 06.09.2024 17:57
Ответ принят как подходящий

Ответ Бурджу идеален. Поскольку я предпочитаю использовать оператор if в awk, вот мой ответ:

awk '{
    if ($0 == "[") {
        in_bracket = 1
        next
    }else if ($0 == "]"){
        in_bracket = 0
    }
    if (in_bracket) {
        print $0
    }
}' a.txt

Другие вопросы по теме

Bash конвертирует последний символ в нижний
Почему в этом случае составная команда (( присваивает значение переменной?
Как использовать цикл bash for для awk для печати строки FPAT, найденной в переменной в кавычках
Bash printf не работает для чисел с плавающей запятой
Bash с использованием сценария Expect выдает ошибку при вызове ssh
Почему моя программа, запущенная из сценария bash, останавливается, когда сценарий находится в фоновом режиме, но только тогда, когда он получает стандартный ввод из именованного канала?
Когда grep ищет шаблоны в файле с кавычками и/или без кавычек в bash?
Как извлечь столбцы из файла CSV, обработать и создать файл CSV на основе результата извлечения и обработки?
Скрипт Bash, который принимает несколько аргументов пути и проверяет, можно ли там успешно создать файлы
Почему bash не завершает выполнение сценария после ошибки внутри скобок?