Usando sed get substring entre duas aspas duplas

14

Eu tenho um arquivo

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)

Agora eu quero extrair apenas os caminhos de arquivo e armazená-lo em outro arquivo. O arquivo de saída é como:

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

Usando sed ou awk, como posso fazer isso?

Eu tentei, sed -n '/"/,/"/p' myfilemas não está funcionando.

XemX
fonte
3
Para aqueles que votam para fechar - Como isso pode ser desconsiderado? É sobre programação de shell !! Isso é PROGRAMAÇÃO, que está no tópico de estouro de pilha!
Jonathan Leffler
2
Bem-vindo ao Stack Overflow. Como você pode ver, ocasionalmente temos problemas com pessoas com coceira no dedo fechando perguntas perfeitamente boas (como esta) com más razões para fechar. Isso não acontece com tanta frequência (ou, não vejo o problema com tanta frequência), mas acontece. Não se esqueça de ler as perguntas frequentes em pouco tempo.
precisa

Respostas:

17

Você pode canalizar o stderr do seu comando rsync para um script awk:

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

Ou para um comando de corte como este:

cut -d'"' -f2
anubhava
fonte
2
Ou, mais curto:cut -d\" -f2
@ AndersJohansson: Obrigado, eu adicionei o seu comando de corte para responder também.
Anubhava 31/12/12
Eu acho que isso não vai funcionar .. como você pode ver o número do campo do caminho do arquivo não é fixo $ 2 ou f2 .. Obrigado!
Na verdade, o rsync sempre escreverá o caminho do arquivo primeiro entre "e "no stderr.
Anubhava
1
@ Jam88: Na verdade, funcionará por causa da maneira como o anubbhava o escreveu. O delimitador de campo está definido para aspas duplas. Isso significa que tudo até a primeira citação dupla (possivelmente uma string vazia) é $1; tudo entre a primeira e a segunda aspas duplas é $2; e tudo depois da segunda citação dupla está em $3( $4, ...). O nome do arquivo está (aparentemente) sempre entre as duas primeiras aspas duplas, portanto essa solução deve funcionar (e funcionou quando eu a testei).
9788 JBJacksonPerfil
6

Usando sed:

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

Isso procura: início da linha, uma série de não-aspas, aspas duplas, captura uma série de não-aspas, aspas duplas e qualquer outra coisa na linha e a substitui pelo material capturado.

$ 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
$

Teste no RHEL 5 Linux com GNU sed, mas apenas usando recursos que funcionariam na versão UNIX ™ da 7ª Edição sed.

Aliás, uma maneira um pouco mais simples de fazer isso é com dois comandos substitutos; altere tudo até e incluindo a primeira aspas duplas para uma sequência vazia (que é uma sequência de zero ou mais sem aspas seguidas por aspas duplas); mude tudo depois do que agora é a primeira citação dupla para nada:

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

Aliás, o comando que você tentou (`sed -n '/" /, / "/ p') imprime de uma linha contendo aspas duplas para a próxima linha que contém aspas duplas, sem editar as linhas. Foi por isso que não pareceu funcionar para você - fez o que você pediu, mas o que você pediu para fazer não foi o que você pretendia pedir.

Em termos de eficiência, é improvável que haja uma diferença mensurável no desempenho. Em termos de facilidade de manutenção, suspeito que este último seja menos exigente para as células cerebrais.

Jonathan Leffler
fonte
1

Se sua versão do grepsuporta Perl-regexp:

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

Resultados:

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

Você também pode tornar isso menos rigoroso, para combinar qualquer coisa entre os duplos, se desejar:

grep -oP '(?<=")[^"]*' file >> anotherfile
Steve
fonte
Você precisa tornar o .*não ganancioso .*?apenas no caso de haver uma citação dupla extra mais adiante na linha? Ou usar [^"]*no lugar de .*?
Jonathan Leffler
-1

Use o operador >> para salvar qualquer saída em um arquivo.

Gostar

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

Então, basta alterar isso para o seu cenário específico usando sed, acrescentando

>> filename

para o comando

AStupidNoob
fonte
O grep -rfaz uma pesquisa recursiva nos diretórios listados nos argumentos ( *). Não está claro qual padrão você tem em mente, mas entenderá greptoda a linha. O objetivo do exercício é coletar informações de parte de uma linha. Se você estiver usando o GNU grep, existem maneiras de fazer isso ( -o); estes não são padrão (exceto na medida em que o GNU define um padrão de fato). Da mesma forma com o uso de expressões regulares do PCRE; essas são outra extensão GNU. Eles são bons se você tiver o GNU grepe não planeja trabalhar em plataformas nas quais o GNU grepnão está disponível por padrão.
9788JacksonPerfil
Desculpe por ter perdido isso, pensei que ele queria saber em geral o que fazer para colocar a saída em um arquivo, e o grep era apenas um exemplo.