#awk
#awk
Вопрос:
Я пытался использовать awk для преобразования файла, разделенного пробелом, в файл, разделенный табуляцией. К моему удивлению, это сработало не так, как ожидалось:
awk -vOFS=
Я ожидал чего-то подобного:
item gram
tomato 500
orange 1500
bread 2000
Чего мне не хватает?
Примечание: многие предложили несколько альтернатив, вот некоторые из них, возможно, кому-то это интересно.
tr -s " " "t" <column.txt
column -t <column.txt
perl -ple "s/s /t/g" <column.txt
sed "s/s /t/" <column.txt
ruby -ple 'gsub(/s /,"t")' <column.txt
python -c "import sys,re; [ sys.stdout.write(re.sub(r' ','t',l)) for l in sys.stdin ]" <column.txt
Комментарии:
1. Лично я просто использую
perl -pli -e 's/s /t/g' file.txt
.2. @Shawn, спасибо, я бы предпочел это, но у меня не было Perl в этой среде. В итоге я использовал
tr -s " " "t" <column.txt
. Это более или менее академический вопрос, поэтому я могу понять, что происходит.3. чтобы добавить к хорошему ответу от @Jotne, вам не хватает одной вещи:
print $0
, что является только одним полем. Я считаю, что это лучше объясняет фразу "если вы просто установите OFS, он ничего не сделает". Он действительно что-то делает, вы просто не используете его. Кстати, это можно было бы улучшить, используяFS
для вырезания столбцов из вашего файла и последующего выводаprint $1,$2
, что явно используетOFS
.4. @DaemonPainter из документации $ 0 означает полную запись, а не поле, и я предположил, что она отличается от $ 1, $ 2 ... и т.д.
5. да, действительно. В конце концов, все, что
$x
вы просите напечатать, выводится в одно поле. Таким образом, только для печати$0
не будет использоваться разделитель полей вывода. Когда я говорю, чтоprint $1,$2
это явно используетOFS
, это происходит из-за запятой. Напомним, что для того, чтобы иметь разделитель полей вывода, вам необходимо вывести как минимум два поля.print $0
выводит только один.
Ответ №1:
Попробуйте это:
awk -v OFS='t' '{$1=$1}1' file
Если вы просто установите OFS, он ничего не сделает. При установке $1
на $1
него будет использоваться поле OFS since, поскольку оно изменилось. 1
всегда имеет значение true, поэтому он будет печатать строку. То же, что {print}
Комментарии:
1. Этому есть более простое объяснение, и оно приводится в комментариях под исходным вопросом. В программировании нет необходимости угадывать, многое из этого сводится к хорошим объясненным правилам.
Ответ №2:
awk -v OFS='t' '{$1=$1}1' file
может быть дополнительно сокращен до
mawk 'BEGIN {OFS="t"} (NF==1) || ($1=$1)' file.
$ 1 = $ 1 не является бесплатным. NF==1 обойдет его для любой строки, в которой просто нет пробелов (просто более гибкое универсальное решение). Успешный $1 = $1 возвращает true, поэтому дополнительный } 1' вне фигурных скобок немного излишен.
t' '{print}' column.txt
item gram
tomato 500
orange 1500
bread 2000
Я ожидал чего-то подобного:
Чего мне не хватает?
Примечание: многие предложили несколько альтернатив, вот некоторые из них, возможно, кому-то это интересно.
Комментарии:
1. Лично я просто использую
perl -pli -e 's/s /t/g' file.txt
.2. @Shawn, спасибо, я бы предпочел это, но у меня не было Perl в этой среде. В итоге я использовал
tr -s " " "t" <column.txt
. Это более или менее академический вопрос, поэтому я могу понять, что происходит.3. чтобы добавить к хорошему ответу от @Jotne, вам не хватает одной вещи:
print $0
, что является только одним полем. Я считаю, что это лучше объясняет фразу «если вы просто установите OFS, он ничего не сделает». Он действительно что-то делает, вы просто не используете его. Кстати, это можно было бы улучшить, используяFS
для вырезания столбцов из вашего файла и последующего выводаprint $1,$2
, что явно используетOFS
.4. @DaemonPainter из документации $ 0 означает полную запись, а не поле, и я предположил, что она отличается от $ 1, $ 2 … и т.д.
5. да, действительно. В конце концов, все, что
$x
вы просите напечатать, выводится в одно поле. Таким образом, только для печати$0
не будет использоваться разделитель полей вывода. Когда я говорю, чтоprint $1,$2
это явно используетOFS
, это происходит из-за запятой. Напомним, что для того, чтобы иметь разделитель полей вывода, вам необходимо вывести как минимум два поля.print $0
выводит только один.
Ответ №1:
Попробуйте это:
Если вы просто установите OFS, он ничего не сделает. При установке $1
на $1
него будет использоваться поле OFS since, поскольку оно изменилось. 1
всегда имеет значение true, поэтому он будет печатать строку. То же, что {print}
Комментарии:
1. Этому есть более простое объяснение, и оно приводится в комментариях под исходным вопросом. В программировании нет необходимости угадывать, многое из этого сводится к хорошим объясненным правилам.
Ответ №2:
может быть дополнительно сокращен до
$ 1 = $ 1 не является бесплатным. NF==1 обойдет его для любой строки, в которой просто нет пробелов (просто более гибкое универсальное решение). Успешный $1 = $1 возвращает true, поэтому дополнительный } 1′ вне фигурных скобок немного излишен.