Структура команды sed:
s/— команда substitute (замена)[^ ]* \([^ ]*\).*— шаблон поиска (pattern)/— разделитель\1— замена (replacement)/— завершающий разделитель
Что такое sed и что такое awd. Примеры использования тут
Пошаговый разбор шаблона поиска:
1. [^ ]*
text
[^ ] - класс символов, НЕ пробел (любой символ кроме пробела) * - ноль или более повторений предыдущего элемента
Вместе: [^ ]* = «ноль или более любых символов, кроме пробела»
- В строке «Hello World Test» это соответствует «Hello»
2. (пробел)
text
- обычный пробел (литерал)
- Соответствует пробелу между «Hello» и «World»
3. \( и \)
text
\( ... \) - захватывающая группа (группировка с запоминанием)
- В sed скобки экранируются обратным слэшем для создания группы
- Содержимое группы будет доступно как
\1
4. [^ ]* внутри группы
text
Внутри \( ... \): [^ ]*
- То же самое: «ноль или более любых символов кроме пробела»
- В нашем случае соответствует «World»
- Это группа 1 (запомненная часть)
5. .*
text
. - любой одиночный символ (кроме перевода строки) * - ноль или более повторений
Вместе: .* = «ноль или более любых символов»
- В строке соответствует » Test» (пробел + «Test»)
Итоговое соответствие для «Hello World Test»:
text
Шаблон: [^ ]* \([^ ]*\) .*
| | | |
| | | " Test" (остаток строки)
| | "World" (группа 1)
| пробел
"Hello" (первое слово)
Полное соответствие: Hello World Test (вся строка)
Разбор части замены /\\1/:
\1— ссылка на первую захватывающую группу (то, что в первых\(...\))- В нашем случае группа 1 содержит
World
Как это работает:
- Находится вся строка по шаблону
- Из найденного извлекается группа 1 («World»)
- Вся найденная строка заменяется на содержимое группы 1
- Результат: «World»
Разрыв страницы
Давайте разберем эту конструкцию sed подробно, на примерах и с вариациями.
Основная команда:
bash
echo "Hello World Test" | sed 's/[^ ]* \([^ ]*\).*/\1/'
Результат: World
Давайте разберем, как она работает, а затем применим к ps и посмотрим на модификации.
1. Детальный разбор исходного выражения
Выражение: 's/[^ ]* \([^ ]*\).*/\1/'
s/— команда замены (substitute)./— разделитель.[^ ]*— шаблон, означающий «ноль или более символов, которые НЕ пробел».[^ ]— это любой символ, кроме пробела,*— повторение 0 или более раз.- (пробел) — просто пробел в строке.
\([^ ]*\)— Ключевая часть! Это группа захвата (capturing group), обозначенная скобками\(и\). Она захватывает «ноль или более символов, которые НЕ пробел». Именно это попадет в\1..*— ноль или более любых символов (остаток строки)./— разделитель между шаблоном и заменой.\1— обратная ссылка (backreference) на текст, захваченный первой группой\(...\). Это то, что будет выведено вместо всей строки./— закрывающий разделитель.
Как это работает на строке "Hello World Test":
[^ ]*жадным образом съедает"Hello".- Затем идет обязательный (пробел). Он совпадает с пробелом после
Hello. - Далее идет группа захвата
\([^ ]*\). Она захватывает следующее слово без пробелов —"World". Теперь\1 = "World". .*съедает все остальное: пробел и"Test".- Вся исходная строка (
Hello World Test) сопоставлена с шаблоном. sedзаменяет всю сопоставленную строку на содержимое\1, то есть на"World".
Итог: Из строки извлекается второе слово.
2. Применение к команде ps
Команда ps выводит список процессов. По умолчанию вывод выглядит примерно так:
text
PID TTY TIME CMD 12345 pts/0 00:00:00 bash 67890 pts/0 00:00:00 ps
Давайте применим наш sed:
bash
ps | sed 's/[^ ]* \([^ ]*\).*/\1/'
Что произойдет для каждой строки вывода ps:
- Первая строка (
PID TTY ...):[^ ]*съест начальные пробелы? Нет! Здесь важно:[^ ]— это «не пробел». В начале строки идут пробелы. Шаблон[^ ]*означает «ноль или более НЕ пробелов». Пробелы — это пробелы, они НЕ подходят под[^ ]. Поэтому совпадение будет длиной 0 символов.- Дальше идет пробел в шаблоне. В строке после 0 символов сразу идет пробел? Да, первый символ строки — пробел. Совпадение есть.
- Группа
\([^ ]*\)захватывает первое не-пробельное слово после этого начального пробела. Это"PID". .*съедает все остальное.- Вся строка заменяется на
\1, т.е."PID".
- Вторая строка (
12345 pts/0 ...):[^ ]*снова не может съесть начальные пробелы (они не подходят под[^ ]), совпадение длины 0.- Пробел в шаблоне совпадает с первым пробелом строки.
- Группа
\([^ ]*\)захватывает первое не-пробельное слово:"12345". - Замена на
\1дает"12345".
Вывод команды будет примерно таким:
text
PID 12345 67890
Мы извлекли второй столбец (первое не-пробельное слово после возможных начальных пробелов) вывода ps.
3. Вариации и примеры
Вариация 1: 's/[^1]* \([^ ]*\).*/\1/'
Здесь изменилось начало: [^1]* вместо [^ ]*.
[^1]*означает: «ноль или более символов, которые НЕ цифра1«.- Это очень сильно меняет логику. Теперь выражение ищет первый блок символов, не содержащий
1, затем пробел, а потом захватывает следующее слово.
Пример с echo "Hello World Test":
bash
echo "Hello World Test" | sed 's/[^1]* \([^ ]*\).*/\1/'
[^1]*будет жадничать, но не может съесть символ1. В строке"Hello World Test"вообще нет1, поэтому[^1]*съедает всю строку до конца.- После этого в шаблоне ожидается пробел. Но строка уже закончилась. Совпадения НЕТ.
sedне находит совпадения с шаблоном и просто выводит исходную строку.
Результат:Hello World Test(без изменений).
Пример с более показательной строкой:
bash
echo "Test 123 one two" | sed 's/[^1]* \([^ ]*\).*/\1/'
[^1]*начинает есть. Можно естьT,e,s,t, пробел. Цифра1не встречалась, можно продолжать. Дальше идет2.2— это не1, можно есть. Дальше идет3.3— это не1, можно есть. Дальше пробел. Пробел — не1, можно есть. Съели"Test 123 ".- Стоп! Следующий символ —
o(от слова"one").o— не1, можно было бы есть, но дальше в шаблоне ожидается пробел. Мы находимся на символеo, который не пробел. Значит, мы должны откатиться (backtrack), чтобы найти место, где выполнится условие «пробел после[^1]*«. [^1]*отдает последний съеденный пробел. Теперь мы съели"Test 123", а следующий символ в строке — это пробел.- Пробел в шаблоне совпадает с пробелом в строке. Отлично!
- Группа
\([^ ]*\)захватывает следующее слово:"one". - Замена на
\1дает"one".
Результат:one
Вывод: [^1]* ищет отрезок до первого вхождения цифры 1 или до момента, когда после него будет пробел для продолжения шаблона.
Вариация 2: 's/[^3]* \([^ ]*\).*/\2/'
Здесь два важных изменения:
[^3]*— «ноль или более символов, которые НЕ цифра3«.\2— ссылка на вторую группу захвата\(...\). Но в нашем шаблоне определена только одна группа захвата!
Что произойдет?
В sed, если вы ссылаетесь на несуществующую группу (например, \2, когда есть только \1), поведение зависит от реализации. Чаще всего:
- GNU
sed: вставляет пустую строку. - BSD
sed(macOS): может выдать ошибку или вставить литеральный текст\2.
Пример (GNU sed):
bash
echo "Hello 123 World 456" | sed 's/[^3]* \([^ ]*\).*/\2/'
[^3]*будет жадничать, пока не встретит3или не сможет выполнить весь шаблон. Строка"Hello 123 World 456"содержит3в подстроке"123".[^3]*съест"Hello 12"(это все символы до первой3).- Пробел в шаблоне. Следующий символ в строке после
"Hello 12"— это3. Это не пробел. Совпадения нет.sedначинает backtracking. - … (процесс backtracking, чтобы найти подходящее совпадение) …
- Допустим, в конце концов, находится совпадение (например, если бы строка была другой). Но даже если совпадение найдется и группа
\1захватит какой-то текст, мы просим заменить всю строку на\2. - Поскольку второй группы захвата нет,
\2заменяется на пустую строку.
Результат (GNU sed):<пустая строка>(или исходная строка, если совпадения не было).
Чтобы это работало, нужно две группы:
bash
echo "first second third" | sed 's/\([^ ]*\) \([^ ]*\) \([^ ]*\)/\2/'
Здесь:
\([^ ]*\)— первая группа (захватит"first"),\1.\([^ ]*\)— вторая группа (захватит"second"),\2.\([^ ]*\)— третья группа (захватит"third"),\3.- Замена на
\2выведет"second".
Результат:second
4. Простые задачи и их решение с помощью модификаций этого шаблона
Задача 1: Извлечь первое слово строки.
bash
echo "Hello World Test" | sed 's/\([^ ]*\).*/\1/' # Результат: Hello # Группа захвата стоит ДО пробела и "жадно" захватывает первое слово.
Задача 2: Извлечь последнее слово строки.
bash
echo "Hello World Test" | sed 's/.* \([^ ]*\)/\1/' # Результат: Test # `.* ` жадным образом съедает всё до последнего пробела, а группа захвата берет оставшееся слово.
Задача 3: Извлечь третье слово строки.
bash
echo "one two three four five" | sed 's/[^ ]* [^ ]* \([^ ]*\).*/\1/' # Результат: three # Добавили еще один блок `[^ ]* ` перед группой захвата, чтобы "пропустить" первые два слова.
Задача 4: Поменять местами первое и второе слово.
bash
echo "Hello World Test" | sed 's/\([^ ]*\) \([^ ]*\)/\2 \1/' # Результат: World Hello Test # Две группы захвата: \1 = "Hello", \2 = "World". Меняем их местами в замене.
Задача 5: Удалить всё, начиная со второго слова.
bash
echo "Hello World Test Example" | sed 's/\([^ ]*\).*/\1/' # Результат: Hello # Похоже на задачу 1. Группа захватывает первое слово, `.*` — всё остальное, заменяем на первое слово.
Итог:
- Базовое выражение
's/[^ ]* \([^ ]*\).*/\1/'— это мощный инструмент для извлечения N-го слова из строки (в данном случае второго, так как перед группой захвата стоит один блок[^ ]*). - Меняя класс символов в
[^...]*, вы меняете условие «пропуска» начальной части строки. - Меняя номер в
\N, вы управляете тем, какая из захваченных групп будет выведена. Количество групп должно соответствовать номеру. - Этот шаблон идеально подходит для обработки табличного вывода команд типа
ps,ls -l,df, где нужно извлечь конкретный столбец.
Восстановление страницы
Разрыв 2
Давайте разберем создание классов символов в регулярных выражениях для sed. Синтаксис [^ ] создает отрицательный класс символов. Чтобы создать нужные классы, нужно понимать базовые правила.
Восстановление 2
Эквиваленты в других инструментах:
В awk (проще):
bash
echo "Hello World Test" | awk '{print $2}'
В sed с другими подходами:
bash
# Удалить все до первого пробела и после второго слова echo "Hello World Test" | sed 's/^[^ ]* //; s/ .*//' # Только второе слово echo "Hello World Test" | sed -E 's/^[^ ]+ ([^ ]+).*/\1/'
Визуализация процесса:
text
Исходная строка: "Hello World Test"
Шаблон поиска: /[^ ]* \([^ ]*\).*/
├─────┤│├─────┤├─┤
│ │││ ││ │
│ │││ ││ └─ .* = " Test"
│ │││ ││
│ │││ │└─ \) конец группы 1
│ │││ │
│ ││└─────┴─ [^ ]* = "World" (группа 1)
│ ││
│ │└─ \( начало группы 1
│ │
│ └─ пробел
│
└─ [^ ]* = "Hello"
Найдено: "Hello World Test"
Группа 1: "World"
Замена: s/найденное/группа1/
Результат: "World"
Этот паттерн находит первое слово + пробел + второе слово + всё остальное, и заменяет всё найденное на только второе слово.
подставив для тестов группу 2 или 0 то не получил hello и не получил, вот разбираем как
Ключевой момент:
В sed только то, что в \(...\) становится доступным как \1, \2 и т.д.
В нашем шаблоне: [^ ]* \([^ ]*\).*
\([^ ]*\)— это первая и единственная группа[^ ]*перед пробелом НЕ в скобках — не группа.*в конце НЕ в скобках — не группа
Ваши тесты объясняются:
1. \1 — работает
bash
echo "Hello World Test" | sed 's/[^ ]* \([^ ]*\).*/\1/' # Вывод: World
Потому что \1 ссылается на \([^ ]*\), что соответствует «World»
2. \2 — ошибка
bash
echo "Hello World Test" | sed 's/[^ ]* \([^ ]*\).*/\2/' # Ошибка: invalid reference \2
Потому что у нас только одна группа (\1). Группы \2 не существует.
3. \0 — особая история
bash
echo "Hello World Test" | sed 's/[^ ]* \([^ ]*\).*/\0/' # Вывод: Hello World Test
\0 в sed — это вся совпавшая строка, а не группа!
То есть шаблон нашел «Hello World Test», и \0 ссылается на всё это.
Чтобы получить Hello или Test, нужно изменить шаблон:
Получить «Hello» (первое слово):
bash
# Добавляем группу для первого слова echo "Hello World Test" | sed 's/\([^ ]*\) \([^ ]*\).*/\1/' # или echo "Hello World Test" | sed 's/^\([^ ]*\).*/\1/' # Вывод: Hello
Получить «Test» (третье слово):
bash
# Группа для третьего слова echo "Hello World Test" | sed 's/[^ ]* [^ ]* \([^ ]*\)/\1/' # или echo "Hello World Test" | sed 's/.* \([^ ]*\)$/\1/' # последнее слово # Вывод: Test
Пример с несколькими группами:
bash
echo "Hello World Test" | sed 's/\([^ ]*\) \([^ ]*\) \([^ ]*\)/\1-\2-\3/' # Вывод: Hello-World-Test # Группы: \1=Hello, \2=World, \3=Test echo "Hello World Test" | sed 's/\([^ ]*\) \([^ ]*\) \([^ ]*\)/\2/' # Вывод: World (вторая группа) echo "Hello World Test" | sed 's/\([^ ]*\) \([^ ]*\) \([^ ]*\)/\3/' # Вывод: Test (третья группа)
Таблица групп для разных шаблонов:
| Шаблон sed | Группы | Что доступно |
|---|---|---|
[^ ]* \([^ ]*\).* | \([^ ]*\) = 1 группа | \1 = «World» |
\([^ ]*\) [^ ]* [^ ]* | \([^ ]*\) = 1 группа | \1 = «Hello» |
[^ ]* [^ ]* \([^ ]*\) | \([^ ]*\) = 1 группа | \1 = «Test» |
\([^ ]*\) \([^ ]*\) \([^ ]*\) | 3 группы | \1=»Hello», \2=»World», \3=»Test» |
Правила sed для групп:
- Только
\(...\)создают нумерованные группы (\1,\2, …) \0— всегда вся совпавшая строка (даже без групп)- Нумерация групп идет по порядку открывающих
\( - Максимум 9 групп (
\1…\9) в старом sed
Ваши примеры с объяснением:
bash
# Исходный: [^ ]* \([^ ]*\).* # Только World в скобках -> только \1 # Чтобы получить Hello: sed 's/\([^ ]*\) .*/\1/' # Hello в скобках # Чтобы получить Test: sed 's/.* \([^ ]*\)$/\1/' # Test в скобках, .* до пробела # Чтобы получить всё кроме World: sed 's/\([^ ]*\) \([^ ]*\) \(.*\)/\1 \3/' # Hello Test
Практическое правило:
Если хотите что-то извлечь с помощью \номер в sed — оберните это в \(...\) в шаблоне поиска!
а что бы было без скобок , а какой в этих скобках еще может быть символ или символы и что они означают и может важен порядок этих символов [^ ]* text [^ ] — класс символов, НЕ пробел (любой символ кроме пробела)
разберем что внутри [ ] и что означает конструкция без скобок.
1. Без скобок \(...\)
Без захватывающих скобок:
bash
echo "Hello World Test" | sed 's/[^ ]* [^ ]* .*/REPLACEMENT/' # Находит: "Hello World Test" # Заменяет ВСЮ строку на "REPLACEMENT"
Без \(...\) вы не можете использовать \1, \2 и т.д.
Можете использовать только специальные символы:
&— вся найденная строка\0— то же самое что&(вся найденная строка)
Пример:
bash
echo "Hello World Test" | sed 's/[^ ]* [^ ]* .*/& &/' # Вывод: Hello World Test Hello World Test # & = вся найденная строка echo "Hello World Test" | sed 's/[^ ]* [^ ]* .*/Found: &/' # Вывод: Found: Hello World Test
2. Что внутри [^ ] — это КЛАСС СИМВОЛОВ
Конструкция [...] означает «любой ОДИН символ из перечисленных»
Варианты классов символов:
Базовые:
bash
[abc] # любой из символов: a, b, или c [a-z] # любой символ от a до z [A-Z] # любой символ от A до Z [0-9] # любая цифра [a-zA-Z] # любая буква (латиница)
Специальные внутри [ ]:
bash
[^abc] # НЕ a, НЕ b, НЕ c (любой символ кроме этих) [-.] # дефис или точка (дефис в начале/конце не диапазон) [\]\[] # экранированные квадратные скобки [.*+?] # метасимволы теряют спец. значение внутри [ ]
Ваш случай [^ ]:
bash
[^ ] # любой символ КРОМЕ пробела
# ^ внутри [ ] означает отрицание/инверсию
# пробел - просто символ пробела
3. Что означает [^ ]*:
Разберем по частям:
text
[^ ] - класс: "любой один символ кроме пробела" * - квантификатор: "ноль или более повторений предыдущего"
Вместе: [^ ]* = «ноль или более любых символов кроме пробела»
Примеры соответствия:
bash
"" # соответствует (ноль символов) "a" # соответствует "abc" # соответствует "123" # соответствует "a-b" # соответствует "a b" # НЕ соответствует (есть пробел!)
4. Порядок символов ВНУТРИ [ ]
НЕ важен для большинства символов:
bash
[abc] ≡ [bac] ≡ [cba] # одинаково
ВАЖЕН для:
- Диапазонов
a-z,0-9:bash[a-z] # от a до z (корректно) [z-a] # ошибка или undefined behavior [0-9] # от 0 до 9 (корректно) [9-0] # ошибка - Специальных символов:bash[]-] # ] или — (специальные символы в определенных позициях) [^] # если ^ не первый символ — просто каретка [^-] # ^ первый = отрицание, — не первый = просто дефис
Правила позиционирования внутри [ ]:
text
[^abc] # ^ ПЕРВЫЙ символ = отрицание класса [a^bc] # ^ НЕ первый = просто символ каретки [a-c] # - между символами = диапазон [-ac] # - первый = просто дефис [ac-] # - последний = просто дефис [a\-c] # \- экранированный = просто дефис
5. Примеры с пробелом в классе символов:
bash
# Пробел как обычный символ внутри [] [abc ] # a, b, c, или пробел [a-z ] # любая буква ИЛИ пробел [^ ] # НЕ пробел (ваш случай) [^a-z ] # НЕ буква и НЕ пробел [[:space:]] # POSIX класс: любой пробельный символ (пробел, таб, и т.д.)
6. Сравнение: со скобками \(...\) и без
С захватывающими скобками (группа):
bash
echo "Hello World" | sed 's/\([^ ]*\) \([^ ]*\)/\2 \1/' # Находит: "Hello World" # Группа 1 (\1): "Hello" # Группа 2 (\2): "World" # Замена: "\2 \1" = "World Hello" # Результат: "World Hello"
Без захватывающих скобок:
bash
echo "Hello World" | sed 's/[^ ]* [^ ]*/Replacement/' # Находит: "Hello World" # Нет групп # Заменяет на "Replacement" # Результат: "Replacement" # Или с & (вся найденная строка): echo "Hello World" | sed 's/[^ ]* [^ ]*/Before & After/' # Результат: "Before Hello World After"
7. Практическая разница на примере:
Исходная строка: "John 25 Engineer"
С группами (можно переставлять части):
bash
echo "John 25 Engineer" | sed 's/\([^ ]*\) \([^ ]*\) \([^ ]*\)/\3: \1 (\2 years)/' # Вывод: "Engineer: John (25 years)" # \1=John, \2=25, \3=Engineer
Без групп (только вся строка):
bash
echo "John 25 Engineer" | sed 's/[^ ]* [^ ]* [^ ]*/& - processed/' # Вывод: "John 25 Engineer - processed" # & = "John 25 Engineer"
8. Важные отличия:
| Аспект | Без \(...\) | С \(...\) |
|---|---|---|
| Можно ссылаться | только на всю строку (& или \0) | на части (\1, \2, …) |
| Использование | простая замена | извлечение, перестановка, сложные замены |
| Память | не запоминает части | запоминает части для повторного использования |
| Пример замены | s/pattern/replacement/ | s/\(part1\) \(part2\)/\2 \1/ |
9. Еще пример с [^ ]*:
bash
# Файл с данными: # Name Age City # John 25 NY # Alice 30 LA # Без групп - просто удалить первые 2 слова: sed 's/[^ ]* [^ ]* //' file.txt # Вывод: # City # NY # LA # С группами - извлечь только возраст (второе слово): sed 's/[^ ]* \([^ ]*\) [^ ]*/\1/' file.txt # Вывод: # Age # 25 # 30
Ключевой вывод:[^ ]* = «слово» (последовательность непробельных символов)\(...\) = «запомнить эту часть для использования в замене»
Без \(...\) вы не можете манипулировать отдельными частями найденного текста.
Задачки от простых к сложным
Фразы-ключи для запоминания:
[^ ]= «НЕ пробел» (один любой символ кроме пробела)[^ ]*= «слово» (ноль или больше не-пробелов)\(...\)= «запомни это» (создает группу)\1,\2= «вспомни 1-е, 2-е» (ссылки на группы)&или\0= «всё найденное» (вся совпавшая строка)[abc]= «или a, или b, или c» (класс символов)[a-z]= «от a до z» (диапазон символов)[^abc]= «НЕ a, НЕ b, НЕ c» (отрицание класса)
ЗАДАЧИ
Уровень 1: Базовый (понимание [^ ]*)
Задача 1.1:
Из строки «apple banana cherry» извлеките только первое слово
bash
echo "apple banana cherry" | sed 's/______/______/' # Ожидаемый вывод: apple
Задача 1.2:
Из строки «John Doe» удалите первое слово
bash
echo "John Doe" | sed 's/______/______/' # Ожидаемый вывод: Doe
Задача 1.3:
Замените всё после первого слова на «…»
bash
echo "Hello beautiful world" | sed 's/______/______/' # Ожидаемый вывод: Hello...
Уровень 2: Группы \(...\)
Задача 2.1:
Поменяйте местами «cat» и «dog» в строке «cat dog»
bash
echo "cat dog" | sed 's/______/______/' # Ожидаемый вывод: dog cat
Задача 2.2:
Из «Name: Alice Age: 25» извлеките только возраст
bash
echo "Name: Alice Age: 25" | sed 's/______/______/' # Ожидаемый вывод: 25
Задача 2.3:
Преобразуйте «file.txt» в «txt.file»
bash
echo "file.txt" | sed 's/______/______/' # Ожидаемый вывод: txt.file
Уровень 3: Классы символов [ ]
Задача 3.1:
Удалите все цифры из строки
bash
echo "abc123def456" | sed 's/______/______/' # Ожидаемый вывод: abcdef
Задача 3.2:
Оставьте только буквы (удалите всё кроме a-z, A-Z)
bash
echo "Hello123 World!@#" | sed 's/______/______/g' # Ожидаемый вывод: HelloWorld
Задача 3.3:
Из «ip: 192.168.1.1» извлеките только IP-адрес
bash
echo "ip: 192.168.1.1" | sed 's/______/______/' # Ожидаемый вывод: 192.168.1.1
Уровень 4: Комбинирование
Задача 4.1:
Из «user=admin role=super» извлеките значение role
bash
echo "user=admin role=super" | sed 's/______/______/' # Ожидаемый вывод: super
Задача 4.2:
Преобразуйте дату «2024-05-20» в «20/05/2024»
bash
echo "2024-05-20" | sed 's/______/______/' # Ожидаемый вывод: 20/05/2024
Задача 4.3:
Из «ERROR 404: Not Found» извлеките код ошибки
bash
echo "ERROR 404: Not Found" | sed 's/______/______/' # Ожидаемый вывод: 404
Уровень 5: Сложные (реальные кейсы)
Задача 5.1:
Из лог-строки извлеките IP-адрес
bash
echo "192.168.1.1 - admin [20/May/2024:10:30:45] GET /index.html" | sed 's/______/______/' # Ожидаемый вывод: 192.168.1.1
Задача 5.2:
Поменяйте формат имени «Doe, John» → «John Doe»
bash
echo "Doe, John" | sed 's/______/______/' # Ожидаемый вывод: John Doe
Задача 5.3:
Извлеките расширение файла из полного пути
bash
echo "/home/user/docs/report.pdf" | sed 's/______/______/' # Ожидаемый вывод: pdf
Уровень 6: Экспертный
Задача 6.1:
Разделить строку на три группы и вывести в обратном порядке
bash
echo "one two three" | sed 's/______/______/' # Ожидаемый вывод: three two one
Задача 6.2:
Из «CPU: 45%, RAM: 78%, DISK: 23%» извлеките все три значения
bash
echo "CPU: 45%, RAM: 78%, DISK: 23%" | sed 's/______/______/' # Ожидаемый вывод: 45 78 23
Задача 6.3:
Удалить всё внутри круглых скобок (включая скобки)
bash
echo "Hello (remove this) World (and this too)" | sed 's/______/______/g' # Ожидаемый вывод: Hello World
ПОДСКАЗКИ ДЛЯ САМОПРОВЕРКИ:
Для уровня 1:
- Используйте
[^ ]*для «слова» s/pattern/replacement/без групп
Для уровня 2:
- Оберните то, что нужно сохранить, в
\(...\) - Используйте
\1,\2для ссылок
Для уровня 3:
[0-9]для цифр[a-zA-Z]для букв[^ ]для «не пробел»- Добавьте
gв конце для глобальной замены
Для уровня 4:
- Комбинируйте
[^ ]*с группами - Используйте конкретные символы как разделители
Для уровня 5:
- Учитывайте специфичные форматы (IP, даты, пути)
- Используйте более точные шаблоны
Для уровня 6:
- Множественные группы
\(...\) - Специальные символы:
\.для точки,\s*для пробелов - Флаги вроде
gдля повторной замены
ПРИМЕР РЕШЕНИЯ (чтобы понять формат):
Простая задача: Из «Hello World» получить «World»
bash
# Решение: echo "Hello World" | sed 's/[^ ]* \([^ ]*\)/\1/' # или echo "Hello World" | sed 's/^[^ ]* //'
Попробуйте