Delimitar por espaço, mas ignorar espaço de barra invertida

8
5678 []
testing,\ group []
[testing []
ip\ 5.6.7.8 []
launch-wizard-1 0.0.0.0/0
456dlkjfa []
1.2.3.4 []
test 1.2.3.4/32 4.3.2.0/23 4.3.2.0/23
default 4.3.2.0/23 4.3.2.0/23
launch-wizard-2 0.0.0.0/0
launch-wizard-3 0.0.0.0/0
2.3.4.5/32 []

Gostaria de obter a primeira coluna acima, mas o problema é que eu preciso tratar \ (espaço de barra invertida) como parte da coluna, portanto, awk '{print $1}'deve me fornecer

5678
testing,\ group
[testing
ip\ 5.6.7.8
launch-wizard-1
456dlkjfa
1.2.3.4
test
default
launch-wizard-2
launch-wizard-3
2.3.4.5/32
CiganoCosmonauta
fonte
\ Sendo tratado como um caractere de escape sempre ou é apenas \ especial? Por exemplo, é a\\ bum campo ou dois?
Gregory Nisbet
@GregoryNisbet eu coloquei em \ é para caractere de escape, não os dados reais
GypsyCosmonaut
1
Se seus dados contivessem uma barra invertida real, como eles seriam representados?
Gregory Nisbet
@GregoryNisbet Good question. Como substituí apenas [[:space:]]por \[[:space:]], os dados originais foram \ intocados em seu lugar. Depois de obter os dados originais na primeira coluna delimitados apenas por espaços e não \[[:space:]], eu seria substituído \[[:space:]]por [[:space:]]e ficaria com os dados originais novamente com \.
GypsyCosmonaut 26/09/18

Respostas:

9

Com o gnu awk ( gawk), você pode usar algumas afirmações de comprimento zero como \<ou \>:

$ echo 'a\ b c' | gawk 'BEGIN{FS="\\> +"} {print $1}'
a\ b

mas, infelizmente, não os cheios-soprado a partir perlou pcre(por ex. (?<!\\), (?<=\w), etc):

$ echo 'a\ b, c' | perl -nle '@a=split /(?<!\\)\s+/, $_; print $a[0]'
a\ b,
mosvy
fonte
5

Você pode substituir \ space por outra coisa e voltar novamente depois.

sed 's/\\ /\\x20/g' data_file | awk '{ print $1; }' | sed 's/\\x20/\\ /g'
pLumo
fonte
Somente com sed: sed 's / \\ / \\ x20 / g; s /. * //; s / \\ x20 / \\ / g' data_file
ctac_
Ou, awk, usando o valor da variável SUBSEP padrão de \034:awk '{gsub(/\\ /,SUBSEP,$0); val=$1; gsub(SUBSEP,"\\ ",val); print val}' file
glenn jackman
5

Com GNU grepou compatível:

grep -Po '^(\\.|\S)*'

Ou com ERE:

grep -Eo '^(\\.|[^\[:space:]])*'

Isso trata \como um operador de citação, para o espaço em branco como um delimitador, mas também para si mesmo. Ou seja, na foo\\ barentrada, ele retorna foo\\.

Stéphane Chazelas
fonte
4

Com apenas sed:

sed -r 's/^((([^\]*\\ ){1,})?[^ ]*).*/\1/' infile

Ou mais curto:

sed -r 's/^(([^\]*\\ )*[^ ]*).*/\1/' infile

Isso (([^\]*\\ ){1,})?[^ ]*corresponde:

  • [^\]*\\: qualquer coisa que não seja uma barra invertida que termine com barra invertida seguida por um espaço (observe que \não é necessário que a classe de personagem interna escape, mas a fora).
  • ([^\]*\\ ){1,}: correspondendo acima com um ou mais tempos de ocorrências.
  • (([^\]*\\ ){1,})?: isso é opcional ao usar (...)?; nós poderíamos usar ([^\]*\\ ){0,}também ou ([^\]*\\ )*.
  • ((([^\]*\\ ){1,})?[^ ]*): corresponde acima do que é opcional, seguido por qualquer coisa que não seja um espaço e mantenha como correspondência de grupo a \1referência anterior.
  • ((([^\]*\\ ){1,})?[^ ]*).*: corresponde acima (...)e qualquer outra coisa .*.

então é peça de reposição apenas imprima \1qual é a saída:

5678
testing,\ group
[testing
ip\ 5.6.7.8
launch-wizard-1
456dlkjfa
1.2.3.4
test
default
launch-wizard-2
launch-wizard-3
2.3.4.5/32
αғsнιη
fonte