За допомогою sed отримати підрядку між двома подвійними лапками


14

У мене є файл

xyz... rsync: "/home/path/to/file": Permission denied (13) rsync:
"/home/path/to/file1": Permission denied (13) rsync:
"/home/path/to/file2": Permission denied (13) rsync:
"/home/path/to/file3": Permission denied (13)

Тепер я хочу витягти лише файлові контури та зберегти його в інший файл. Вихідний файл виглядає так:

/home/path/to/file 
/home/path/to/file1 
/home/path/to/file2
/home/path/to/file3

Використовуючи sed або awk, як це зробити?

Я спробував, sed -n '/"/,/"/p' myfileале це не працює.


3
Для тих, хто голосує, щоб закрити - Як це може бути поза темою? Йдеться про програмування оболонок !! Це ПРОГРАММУВАННЯ, яке ТЕМА для переповнення стека!
Джонатан Леффлер

2
Ласкаво просимо до переповнення стека. Як бачите, у нас періодично виникають проблеми з людьми, які сверблять тригерними пальцями, закриваючи ідеально хороші запитання (наприклад, цей) із поганими причинами закриття. Це трапляється не все так часто (або я не бачу проблеми вчасно все так часто), але це трапляється. Не забудьте занадто довго читати FAQ .
Джонатан Леффлер

Відповіді:


17

Ви можете передати stderr вашої команди rsync у сценарій awk:

awk -F '"' '{print $2}' 

Або до команди cut, як це:

cut -d'"' -f2

2
Або коротше:cut -d\" -f2

@AndersJohansson: Дякую, я також додав вашу команду cut, щоб відповісти.
анубхава

Я думаю, що це не буде працювати .. так як ви можете бачити номер поля, шлях до файлу не встановлено $ 2 або f2 .. Дякую!

Насправді rsync завжди буде писати файловий шлях спочатку між "і "на stderr.
анубхава

1
@ Jam88: Насправді, вона працюватиме через те, як її написала ануббхава. Розмежувач поля встановлюється подвійною цитатою. Це означає, що все до першої подвійної цитати (можливо, порожній рядок) є $1; все між першою та другою подвійними цитатами є $2; і все після другої подвійної цитати є в $3( $4, ...). Назва файлу (мабуть) завжди знаходиться між першими двома подвійними лапками, тому це рішення повинно працювати (і робилося, коли я його тестував).
Джонатан Леффлер

6

Використання sed:

sed 's/^[^"]*"\([^"]*\)".*/\1/'

Це шукає: початок рядка, серія нецитат, подвійна цитата, фіксує серію нецитат, подвійну цитату та все інше у рядку, і замінює її відзнятим матеріалом.

$ sed 's/^[^"]*"\([^"]*\)".*/\1/' <<'EOF'
> xyz... rsync: "/home/path/to/file": Permission denied (13) rsync:
> "/home/path/to/file1": Permission denied (13) rsync:
> "/home/path/to/file2": Permission denied (13) rsync:
> "/home/path/to/file3": Permission denied (13)
> EOF
/home/path/to/file
/home/path/to/file1
/home/path/to/file2
/home/path/to/file3
$

Тестуйте на RHEL 5 Linux з GNU sed, але лише використовуючи функції, які працювали б у версії UNIX ™ 7-го видання sed.

До речі, дещо простіший спосіб зробити це за допомогою двох команд-замінників; змінити все до і включити першу подвійну цитату на порожню рядок (це послідовність нульових або більше не цитат, а потім подвійна цитата); змінити все після того, що є першою подвійною цитатою ні до чого:

sed 's/^[^"]*"//; s/".*//'

До речі, команда, яку ви спробували (`sed -n '/" /, / "/ p') друкує з одного рядка, що містить подвійну лапочку, до наступного рядка, що містить подвійну лапочку, без редагування рядків взагалі. Ось чому це, здається, не працювало для вас - це робило те, про що ви просили, але те, що ви просили, це не те, що ви мали намір просити.

Що стосується ефективності, то навряд чи буде помітна різниця у продуктивності. З точки зору простоти обслуговування, я підозрюю, що останній менше оподатковує клітини мозку.


1

Якщо ваша версія grepпідтримує Perl-regexp:

grep -oP '(?<=")/home/.*?(?=")' file >> anotherfile

Результати:

/home/path/to/file
/home/path/to/file1
/home/path/to/file2
/home/path/to/file3

Ви також можете зробити це менш суворим, щоб відповідати чому-небудь між парними, якщо хочете:

grep -oP '(?<=")[^"]*' file >> anotherfile

Вам потрібно зробити .*не жадібним .*?лише на випадок, якщо пізніше в рядку буде додаткова подвійна цитата? Або використовувати [^"]*замість .*?
Джонатан Леффлер

-1

Використовуйте оператор >>, щоб зберегти будь-який вихід у файл.

Подобається

grep -r "pattern" * >> file.txt

Тому просто змініть це для вашого конкретного сценарію, використовуючи sed, додавши

>> filename

до команди


grep -rРобить рекурсивний пошук з допомогою будь-яких каталогів , перерахованих в аргументах ( *). Незрозуміло, який шаблон ви маєте на увазі, але grepпідбере всю лінійку. Мета вправи - збір інформації з частини рядка. Якщо ви використовуєте GNU grep, є способи зробити це ( -o); вони нестандартні (за винятком випадків, коли GNU визначає фактичний стандарт). Аналогічно із використанням регулярних виразів PCRE; це ще одне розширення GNU. Вони добре, якщо у вас GNU grepі не плануєте працювати на платформах, де GNU grepза замовчуванням недоступний.
Джонатан Леффлер

Вибачте, що я пропустив це, я думав, що він хоче взагалі знати, що робити, щоб поставити вихід у файл, а grep - лише приклад.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.