управление текстовым файлом, разделенным пробелом

#regex #awk #sed

#регулярное выражение #awk #sed

Вопрос:

У меня есть текстовый файл в следующем формате

 4 This is my test file 4500
5 This is test 6000
6 Not sure how it will work 9000

I want to extract data as follows

Field1 = 4
Field2 = This is my test file
Field3 = 4500
  

Это первая строка, я хочу, чтобы все строки были в этом формате. Кто-нибудь может помочь? Я хотел бы сделать либо sed, либо awk без perl. Я бы предпочел sed и / или awk.

У меня возникли проблемы с полем 2 (которое может быть либо одним словом, либо строкой из нескольких слов), чтобы заключить его в одинарные или двойные кавычки. остальное, я думаю, легко. Пожалуйста, помогите

Комментарии:

1. Я не мог бы назвать это правильным файлом с разделителями, поскольку он не отличает пробелы как разделители от пробелов как значений.

Ответ №1:

Использование sed

 sed -re 's/(S )s (.*)s (S )/Field1 = 1nField2 = 2nField3 = 3/g' file
  

Вывод:

 Field1 = 4
Field2 = This is my test file
Field3 = 4500
Field1 = 5
Field2 = This is test
Field3 = 6000
Field1 = 6
Field2 = Not sure how it will work
Field3 = 9000
  

Комментарии:

1. Будет работать только с некоторыми sed из-за s и n и -r и завершится ошибкой, если «поле 2» содержит какие-либо цифры.

2. Добавление этого ? сделало его еще менее переносимым. Если вы избавитесь от этого и привяжете свой последний сегмент RE к концу строки, я думаю, это будет лучше : /^([0-9] )s (.*)s ([0-9] )$ . Вы даже можете изменить [0-9] s на S s, и тогда он гарантированно будет работать в любом языковом стандарте, и его больше не будет волновать, являются ли эти поля цифрами или нет : /^(S )s (.*)s (S )$/ .

3. Теперь выглядит хорошо, 1. На самом деле я вижу, что вы не привязали последний сегмент RE, и он все еще работает, поэтому вам также не нужно привязывать первый. Все о симметрии …. :-).

4. Спасибо за отзыв.

5. Когда я тестировал обе версии awk и sed с реальными данными, sed вернул данные идеально. Спасибо всем за вашу помощь. Я использую sed. Дааааааааааа хо.

Ответ №2:

Почти всегда легко найти «решение», которое работает для данного набора входных данных, но гораздо сложнее найти тот, который работает период. Действительно подумайте о своем реальном возможном вводе, прежде чем выбирать «решение». Это может не дать желаемого результата, если у вас на входе меньше 3 полей, если это возможно, обновите свой образец ввода и ожидаемый результат, чтобы показать, как вы хотите, чтобы это обрабатывалось.

 $ awk '{
         f2=$0
         gsub(/^[^[:space:]] [[:space:]] |[[:space:]] [^[:space:]] $/,"",f2)
         print "field1 =", $1
         print "field2 =", f2
         print "field3 =", $NF
}' file
field1 = 4
field2 = This is my test file
field3 = 4500
field1 = 5
field2 = This is test
field3 = 6000
field1 = 6
field2 = Not sure how it will work
field3 = 9000
  

Комментарии:

1. Хорошее решение с использованием awk. 1

Ответ №3:

Это не идеально, но вы можете попробовать использовать это awk :

 awk '{s=$1;e=$NF; $1=$NF=""; gsub(/^  |  $/, ""); 
            printf "f1=<%s>,f2=<%s>,f3=<%s>n", s, $0, e}' file
f1=<4>,f2=<This is my test file>,f3=<4500>
f1=<5>,f2=<This is test>,f3=<6000>
f1=<6>,f2=<Not sure how it will work>,f3=<9000>
  

Комментарии:

1. Это отлично работает. Я просто хотел заключить второе поле в кавычки, чтобы я мог поместить вокруг него разделитель каналов. Спасибо.

2. Рад узнать, что это сработало, можете ли вы пометить ответ как принятый, нажав на галочку в левом верхнем углу моего ответа.

3. Единственная проблема с этим решением заключается в том, что оно изменит любое пустое пространство, присутствующее в «поле 2», так что, например, табуляции или последовательности пробелов станут символами с одним пробелом.