Разграничить пробелом, но игнорировать обратную косую черту

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 []

Я хотел бы получить первый столбец из вышеперечисленного, но подвох в том, что мне нужно рассматривать \ (пространство с обратной косой чертой) как часть столбца, поэтому awk '{print $1}'должен дать мне

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
GypsyCosmonaut
источник
Всегда ли \ рассматривается как escape-символ или он только \ особенный? Например, a\\ bодно поле или два?
Грегори Нисбет,
@GregoryNisbet, который я вставил в \, предназначен для экранирующего символа, а не для реальных данных
GypsyCosmonaut
1
Если ваши данные содержат реальную обратную косую черту, как они будут представлены?
Грегори Нисбет
@GregoryNisbet Хороший вопрос. Поскольку я заменил только [[:space:]]на \[[:space:]], исходные данные заменили их. После того , как исходные данные в первой колонке , ограниченной только пробелами и не \[[:space:]], я бы заменить \[[:space:]]с , [[:space:]]и я осталась бы с исходными данными обратно , которая имеет \.
GypsyCosmonaut

Ответы:

9

с помощью gnu awk ( gawk) вы можете использовать некоторые утверждения нулевой длины, такие как \<или \>:

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

но, к сожалению, не полноценные из perlили pcre(например (?<!\\), (?<=\w)и т. д.):

$ echo 'a\ b, c' | perl -nle '@a=split /(?<!\\)\s+/, $_; print $a[0]'
a\ b,
mosvy
источник
5

Вы можете заменить \ space чем-то другим и потом снова вернуться.

sed 's/\\ /\\x20/g' data_file | awk '{ print $1; }' | sed 's/\\x20/\\ /g'
pLumo
источник
Только с sed: sed 's / \\ / \\ x20 / g; s /. * //; s / \\ x20 / \\ / g' data_file
ctac_
Или, awk, используя значение переменной SUBSEP по умолчанию \034:awk '{gsub(/\\ /,SUBSEP,$0); val=$1; gsub(SUBSEP,"\\ ",val); print val}' file
glenn jackman
5

С GNU grepили совместимым:

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

Или с ERE:

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

Это рассматривается \как оператор цитирования, для пробела в качестве разделителя, но и для самого себя. То есть при foo\\ barвводе возвращается foo\\.

Стефан Шазелас
источник
4

С просто sed:

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

Или короче:

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

Это (([^\]*\\ ){1,})?[^ ]*соответствует:

  • [^\]*\\: все, что не является обратной косой чертой, которая заканчивается обратной косой чертой, за которой следует пробел (обратите внимание, что \внутри класса символов не требуется экранировать, а снаружи -).
  • ([^\]*\\ ){1,}: сопоставление выше с одним или несколькими моментами вхождений.
  • (([^\]*\\ ){1,})?: это необязательно при использовании (...)?; мы могли бы использовать ([^\]*\\ ){0,}вместо этого или ([^\]*\\ )*.
  • ((([^\]*\\ ){1,})?[^ ]*): совпадения выше, которые являются необязательными, за которыми следует все, что не является пробелом, и хранится как групповое совпадение с \1обратной ссылкой.
  • ((([^\]*\\ ){1,})?[^ ]*).*: совпадения выше (...)и все остальное .*.

тогда заменяющая часть просто распечатывает, \1которая является выходом:

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нιη
источник