Use o espaço como um delimitador com o comando cut

328

Eu quero usar o espaço como um delimitador com o cutcomando

Que sintaxe posso usar para isso?

Jaelebi
fonte
42
falso, a página do manual para o corte não explica isso e é, em geral, não informativo
UncleZeiv
2
Além disso, "corte de informações" não é uma melhoria neste caso.
Cardiff space man
3
@ mklement0, se bem me lembro, estava respondendo a um comentário que foi excluído desde então, que estava descartando essa pergunta como respondida na página de manual, que na minha opinião era "falsa", independentemente de haver uma boa razão para isso. ou não - agora, enquanto eu admitem que pode haver uma boa razão para esta falta de informação, eu ainda acho que a documentação sem exemplos de uso comum é frequentemente pelo menos irritante, quando não totalmente inútil
UncleZeiv
3
@UncleZeiv Entendi; Obrigado por esclarecer; dado o interesse nesta pergunta, é justo supor que a manpágina não seja suficiente. Vamos dar uma olhada: " -d delimUse delimcomo o caractere delimitador de campo em vez do caractere de tabulação". (BSD cut, mas a versão GNU e a especificação POSIX praticamente afirmam o mesmo). O uso de um shell para invocar cut- o caso típico - exige, portanto, que você saiba como geralmente passar um espaço como argumento usando a sintaxe do shell , o que, sem dúvida, não cuté o trabalho da página de manual. Exemplos do mundo real sempre ajudam, no entanto, e a página de manual do GNU não possui.
Mklement0
4
embora a resposta selecionada seja tecnicamente correta, considere selecionar a resposta mais recente e abrangente por @ mklement0 como a resposta canônica para que ela seja filtrada para o topo.
David LeBauer

Respostas:

367
cut -d ' ' -f 2

Onde 2 é o número do campo delimitado por espaço que você deseja.

RichieHindle
fonte
2
você pode dizer ao cut para usar qualquer número de um determinado caractere como delimitador, como no RegEx? por exemplo qualquer número de espaços, por exemplo, \ s +
amphibient
3
@foampile Não, eu não acredito que você possa.
Jonathan Hartley
6
Você não pode usar expressões regulares com cut, mas você pode com cutsque tenta "consertar" todas as cutlimitações: github.com/arielf/cuts
arielf
você pode obter todos os terceiros campos delimitados por espaço? como cut -d ' ' -f 3,6,9,12,15,18sem ter que especificar todos os números?
Monocito 17/04
169

Geralmente, se você usa espaço como delimitador, deseja tratar vários espaços como um, porque analisa a saída de um comando que alinha algumas colunas com espaços. (e a pesquisa no google por isso me leva aqui)

Nesse caso, um único cutcomando não é suficiente e você precisa usar:

tr -s ' ' | cut -d ' ' -f 2

Ou

awk '{print $2}'
BeniBela
fonte
2
Obrigado pelo exemplo de uso do awk, exatamente o que eu precisava.
Spazm
44

Para complementar as respostas úteis existentes; dica do suporte ao QZ por me incentivar a postar uma resposta separada:

Dois mecanismos distintos entram em jogo aqui:

  • (a) se cut ele próprio exige que o delimitador (espaço, neste caso) passado para a -dopção seja um argumento separado ou se é aceitável anexá-lo diretamente a -d.

  • (b) como o shell geralmente analisa argumentos antes de passá-los para o comando que está sendo chamado.

(a) é respondida por uma citação das diretrizes POSIX para utilidades (ênfase minha)

Se a SINOPSE de um utilitário padrão mostra uma opção com um argumento-opção obrigatório , [...] um aplicativo em conformidade deve usar argumentos separados para essa opção e seu argumento-opção . No entanto , uma implementação em conformidade também deve permitir que os aplicativos especifiquem a opção e o argumento da opção na mesma sequência de argumentos sem caracteres intervenientes .

Em outras palavras: nesse caso, como -do argumento de opção é obrigatório , você pode escolher se deseja especificar o delimitador como :

  • (s) OUTROS: um argumento separado
  • (d) OU: como um valor diretamente associado a-d .

Depois que você escolhe (s) ou (d), é a análise literal de cadeia do shell - (b) - que importa:

  • Com abordagem (s) , todas as seguintes formas são equivalentes:

    • -d ' '
    • -d " "
    • -d \<space> # <space> used to represent an actual space for technical reasons
  • Com a abordagem (d) , todas as seguintes formas são EQUIVALENTES:

    • -d' '
    • -d" "
    • "-d "
    • '-d '
    • d\<space>

A equivalência é explicada pelo processamento literal de cadeia do shell :

Todas as soluções acima resultam na mesma sequência exata (em cada grupo) quando as cut :

  • (s) : cut-d, como seu próprio argumento, seguido por um argumento separado que contém um caractere de espaço - sem aspas ou \prefixo !.

  • (d) : cut-d mais um caractere de espaço - sem aspas ou \prefixo! - como parte do mesmo argumento.

A razão pela qual os formulários nos respectivos grupos são basicamente idênticos é dupla, com base em como o shell analisa literais de strings :

  • O shell permite que o literal seja especificado como é através de um mecanismo chamado de citação , que pode assumir várias formas :
    • strings entre aspas simples : o conteúdo interno '...'é tomado literalmente e forma um único argumento
    • strings com aspas duplas : o conteúdo dentro "..."também forma um argumento único , mas está sujeito a interpolação (expande referências variáveis, como $varsubstituições de comandos ( $(...)ou `...`) ou expansões aritméticas ( $(( ... )))).
    • \-citação de caracteres individuais : um caractere\ anterior a um único faz com que esse caractere seja interpretado como um literal.
  • Citando é complementado por remoção de citação , o que significa que uma vez que a casca tem analisado uma linha de comando, ele remove os caracteres de citação dos argumentos (que encerram '...'ou "..."ou \instâncias) - assim, o ser comando invocado nunca vê as aspas .
mklement0
fonte
36

Você também pode dizer:

cut -d\  -f 2

Observe que existem dois espaços após a barra invertida.

Chas. Owens
fonte
30
A pessoa que sabe que '\' escapa do próximo caractere seria muito cuidadosa ao anotar o que viria a seguir. Usar '\' para escapar de caracteres espaciais como esse é um idioma muito comum.
Jonathan Hartley
3
@ Jonathan Hartley comumente maioria dos códigos são ilegíveis na verdade :)
Luca Borrione
1
De uma perspectiva linux / unix, \ foi minha primeira tentativa e funcionou. Concordo que é menos óbvio quando comparado a ' ', mas tenho certeza que muitos ficam felizes em lê-lo aqui como garantia de comportamento. Para uma melhor compreensão, consulte o comentário de @ mklement0 abaixo.
Tresf
@ Correção de JonathanHartley: "a pessoa egoísta que sabe que '\' escapa do próximo personagem e assume que todo mundo sabe disso também". Para projetos pessoais, isso não se aplica, mas em um ambiente de equipe, essa suposição é muito perigosa (e potencialmente cara).
Eduard Nicodei # 13/17
1
@EduardNicodei Oh, eu concordo. Estávamos falando sobre leitores do código ("quem nota ...?"), Não autores. Mas também, em algumas equipes, é bom assumir um certo nível de proficiência. Depende do meio ambiente.
Jonathan Hartley
5

Eu só descobri que você também pode usar "-d ":

cut "-d "

Teste

$ cat a
hello how are you
I am fine
$ cut "-d " -f2 a
how
am
fedorqui 'Então pare de prejudicar'
fonte
1
De fato - ou '-d '.
usar o seguinte código
3
Note-se que a partir cutda perspectiva de todos os seguintes são idênticos: "-d ", '-d ', -d" ", -d' ', e -d\<space>: todas as formas directamente inclua o argumento opção (um espaço) para a opção ( -d) e resultado na mesma seqüência exata no momento em que cutvê-los: um único argumento contendo d seguido de um espaço, depois da concha foi realizada citação remoção
mklement0
1
A resposta de @ mklement0 deve ser a resposta. É o mais abrangente nesta página (mesmo que seja um comentário).
Tresf
@QZSupport: Agradeço o sentimento e o incentivo - ele me inspirou a postar minha própria resposta com informações adicionais.
precisa saber é o seguinte
1
Lol descoberta fascinante!
Harry
4

Você não pode fazer isso facilmente com o corte se os dados tiverem, por exemplo, vários espaços. Eu achei útil normalizar a entrada para facilitar o processamento. Um truque é usar o sed para normalização como abaixo.

echo -e "foor\t \t bar" | sed 's:\s\+:\t:g' | cut -f2  #bar
Anssi
fonte
3

scut , um utilitário semelhante a um corte (mais inteligente, mas mais lento que eu fiz) que pode usar qualquer regl perl como um token de interrupção. Quebrar em espaço em branco é o padrão, mas você também pode quebrar em expressões regulares com vários caracteres, expressões alternativas, etc.

scut -f='6 2 8 7' < input.file  > output.file

portanto, o comando acima quebraria colunas no espaço em branco e extrairia as colunas (com base em 0) 6 2 8 7 nessa ordem.

Harry Mangalam
fonte
0

Eu tenho uma resposta (eu admito uma resposta um pouco confusa) que envolve sedexpressões regulares e grupos de captura:

  • \S* - primeira palavra
  • \s* - delimitador
  • (\S*) - segunda palavra - capturada
  • .* - resto da linha

Como sedexpressão, o grupo de captura precisa ser escapado, ou seja, \(e \).

O \1retorna uma cópia do grupo capturado, ou seja, a segunda palavra.

$ echo "alpha beta gamma delta" | sed 's/\S*\s*\(\S*\).*/\1/'
beta

Quando você olha para essa resposta, é um pouco confuso e, você pode pensar, por que se preocupar? Bem, espero que alguns digam "Aha!" e usará esse padrão para resolver alguns problemas complexos de extração de texto com uma única sedexpressão.

Stephen Quan
fonte