PDA

Просмотр полной версии : AWK (shell, Linux)


ΛLIEN
17.05.2007, 18:56
Вопрос такой возник по awk-у, может есть простые решения.

Есть файл формата:
поле1 "поле 2" поле3
поле1 "поле 2" поле3
.... и т.д.

Естественно, строковое поле "поле 3" разбивается на два. В итоге имеем
$1 = поле1
$2 = "поле
$3 = 2"
$4 = поле3

А хотелось бы:
$1 = поле1
$2 = "поле 2"
$3 = поле3

Заниматься тем, что самому парсить $0 и вытаскивать отдельно значения в кавычках не улыбает, тем более, что пробел между кавычек может быть не один (или вообще табулятор). Есть ли более простые решения при помощи изменения, к примеру, FS или как-то еще?

ps: к man awk не отсылать. Не нашел я там ничего по этому поводу. =)

pps: интересуют решения только для awk.

Прохожий
17.05.2007, 19:03
cat testfile |awk 'BEGIN {FS="\""}; {print $1, $2, $3}'

и все-таки man awk :)

ΛLIEN
17.05.2007, 19:10
cat testfile |awk 'BEGIN {FS="\""}; {print $1, $2, $3}'

А теперь представь себе, что строка немного другая:

поле1 "поле 2" "поле 3"

Прохожий
17.05.2007, 19:23
это не "немного другая", это совсем другая.
а в следующий раз что будет, бинарный файл? :)

ΛLIEN
17.05.2007, 19:29
это не "немного другая", это совсем другая.
а в следующий раз что будет, бинарный файл? :)

Нет. =) Бинарного не будет. Просто в файле строковые значения заключены в кавычки, а числовые без. Естественно, я привел упрощенный вариант формата, где только одно поле в кавычках, тогда все просто. А если не одно? Вот тут начинаются проблемы.

Прохожий
17.05.2007, 19:31
ты лучше файл выложи, а то мало ли, чего там еще ты забыл :)

ΛLIEN
17.05.2007, 19:41
ты лучше файл выложи, а то мало ли, чего там еще ты забыл :)

Возвращаться на работу, чтоб выложить файл, мне как-то лениво. =)
Так что может верить на слово, строки файла аля:

число число "какой-то текст" "еще какой-то текст" число число....

Прохожий
17.05.2007, 19:48
ну я ж говорил :) у тебя все вперемешку идет, что ли? выше ты нарисовал так, как будто у тебя строго три поля в строке.

и что это у тебя за работа, на которую удаленно зайти нельзя?

ΛLIEN
17.05.2007, 19:57
ну я ж говорил :) у тебя все вперемешку идет, что ли? выше ты нарисовал так, как будто у тебя строго три поля в строке.
Нет, не в перемешку. В определенном порядке. Числа над числами, строковые над строковыми, но чуЙствую, придется над $0 издеваться своими силами.

Прохожий
17.05.2007, 20:03
так ты можешь хотя бы кусок реального файла показать? ну или сочинить, но чтобы он был таким же, как в реале. издеваться над $0 смысла нет, не для этого awk придуман.

ΛLIEN
17.05.2007, 20:08
так ты можешь хотя бы кусок реального файла показать? ну или сочинить, но чтобы он был таким же, как в реале. издеваться над $0 смысла нет, не для этого awk придуман.

Ок. Сочиняю. =)

1001 "Через тернии к звездам" "Афтар А.Ф." 1955 500 "Лениздат. бла бла бла"

Прохожий
17.05.2007, 20:16
одной строки мало :) еще парочку, а лучше чуть больше. в реальном файле числа и строки идут именно в таком порядке?

ΛLIEN
17.05.2007, 20:18
одной строки мало :) еще парочку, а лучше чуть больше.
У меня фантазии не хватит. =)

в реальном файле числа и строки идут именно в таком порядке?
Считай, что да.

Прохожий
17.05.2007, 20:23
т.е.
1001 "Через тернии к звездам" "Афтар А.Ф." 1955 500 "Лениздат. бла бла бла"
1001 "Через тернии к звездам" "Афтар А.Ф." 1955 500 "Лениздат. бла бла бла"
1001 "Через тернии к звездам" "Афтар А.Ф." 1955 500 "Лениздат. бла бла бла"
1001 "Через тернии к звездам" "Афтар А.Ф." 1955 500 "Лениздат. бла бла бла"
1001 "Через тернии к звездам" "Афтар А.Ф." 1955 500 "Лениздат. бла бла бла"
1001 "Через тернии к звездам" "Афтар А.Ф." 1955 500 "Лениздат. бла бла бла"
1001 "Через тернии к звездам" "Афтар А.Ф." 1955 500 "Лениздат. бла бла бла"
1001 "Через тернии к звездам" "Афтар А.Ф." 1955 500 "Лениздат. бла бла бла"


похоже на реальный файл? потому что задача такая, что решение будет неуниверсально и сильно зависеть от исходных данных.

ΛLIEN
17.05.2007, 20:25
похоже на реальный файл? потому что задача такая, что решение будет неуниверсально и сильно зависеть от исходных данных.
На отсечение ничего не дам, но вроде так.

Прохожий
17.05.2007, 20:28
а ограничение awk only насколько критично? sed использовать можно? он есть везде, где есть shell :)

ΛLIEN
17.05.2007, 20:31
sed использовать можно? он есть везде, где есть shell :)
sed есть.

Прохожий
17.05.2007, 20:34
cat testfile |sed 's/" "/"/g'|awk 'BEGIN {FS="\""}; {print $1,$2,$3,$4,$5}'

ΛLIEN
17.05.2007, 20:47
cat testfile |sed 's/" "/"/g'|awk 'BEGIN {FS="\""}; {print $1,$2,$3,$4,$5}'

Спасибо, завтра попробую.

Прохожий
17.05.2007, 20:50
не, если файл именно в таком виде, то тогда четвертое поле будет содержать "1955 500", а это неправильно. полей должно быть шесть и четвертое должно быть "1955", а пятое "500". ща переделаю, но решение станет еще сильнее привязанным к файлу :)

ΛLIEN
17.05.2007, 20:57
Я так понимаю, ты пробелкавычка заменил на просто кавычка и вместо текст" "текст должно получиться текст""текст и оно уже нормально разделяется через awk?

Прохожий
17.05.2007, 21:05
bash$ cat testfile |sed 's/" "/"/g'|awk 'BEGIN {FS="\""}; {split ($4,a," ")};{print $1,$2,$3,a[1],a[2],$5};'

я заменил кавычкапробелкавычка на просто кавычка и вместо текст" "текст получится текст"текст. разделяется нормально, потому что в FS сказано делить по кавычкам. но нужно еще 1955 500 разделить по пробелу, я это сразу не учел, но вышеприведенный код работает как надо. см:

bash$ cat testfile |sed 's/" "/"/g'|awk 'BEGIN {FS="\""}; {split ($4,a," ")};{print $1};'
1001
1001
1001
1001
1001
1001
1001
1001


bash$ cat testfile |sed 's/" "/"/g'|awk 'BEGIN {FS="\""}; {split ($4,a," ")};{print $2};'
Через тернии к звездам
Через тернии к звездам
Через тернии к звездам
Через тернии к звездам
Через тернии к звездам
Через тернии к звездам
Через тернии к звездам
Через тернии к звездам
bash$ cat testfile |sed 's/" "/"/g'|awk 'BEGIN {FS="\""}; {split ($4,a," ")};{print a[1]};'
1955
1955
1955
1955
1955
1955
1955
1955

ну и так далее. единственное замечание - поля 4 и 5 хранятся не в переменных $4 и $5, а в элементах массива a[1] и a[2], а поле 6 - в переменной $5 :) содержимое остальных переменных соответствует их именам.

ΛLIEN
17.05.2007, 22:16
...содержимое остальных переменных соответствует их именам.
10х еще раз. Надо будет в ближайшее время приобщиться к man sed. =)

Прохожий
17.05.2007, 22:26
не за что :)
sed прост и в 99% случаев достаточно только одной его команды - s.
awk намного более могуч :) и в принципе они вполне взаимозаменяемы, хотя простые вещи вроде замены с использованием регулярных выражений на sed записываются короче, из-за этого я его и пользую :)

если ты с файлом все же напутал - отпишись, я подправлю скриптик. если сам не сможешь, конечно :)

ΛLIEN
19.05.2007, 01:24
отпишись, я подправлю скриптик.
Да нет, не надо. Работает.
/me читает man sed
Так много интересного. =)