На первый взгляд мне показалось, что на это нельзя ответить, кроме как сказать: нет, варианты, которые кажутся бессмысленными, всегда можно найти. Вы можете создать свою собственную программу, которая преднамеренно имеет опции с совершенно бессмысленными названиями. (Конечно, даже тогда вы могли бы сказать, что они значимы в своей бессмысленности, если бы они были намеренно выбраны бессмысленными.)
При дальнейшем рассмотрении, однако, я понял, что двусмысленность в том, что означает семантика параметра, на самом деле является важной и полезной частью того, как командные -параметры строки называются и curl -I
является особенно показательным примером этого.
Как говорит муру , варианты не должны быть семантическими. Но curl
вариант -I
является семантическим. Из завиток (1):
-i/--include
(HTTP) Include the HTTP-header in the output. The HTTP-header includes things like server-name, date of the document, HTTP-version and more...
-I/--head
(HTTP/FTP/FILE) Fetch the HTTP-header only! HTTP-servers feature the command HEAD which this uses to get nothing but the header of a document. When used on a FTP or FILE file, curl displays the file size and last modification time only.
-i
— это краткая форма --include
, что приводит к включению заголовка HTTP. Хотя -I
является краткой формой --head
, семантически это более сильная форма -i
, поскольку -i
дает вам заголовок HTTP, -I
дает вам только заголовок HTTP.
Это дает представление о вашем более широком вопросе :существует множество различных критериев, по которым можно судить о том, является ли имя параметра семантическим.Когда параметр является семантическим , он может быть преднамеренным или непреднамеренным. Если вас интересует только то, существует ли какой-либо способ запомнить параметр как семантический, тогда да, вы всегда можете придумать причину, по которой имя связано с его значением.
Некоторые опции являются семантическими более чем одним способом. Вы можете заставить GNUgrep
отображать строки, смежные с соответствующими строками, с помощью -A
для после , -B
для до и -C
для контекста . что дает вам обоим. Таким образом, краткие формы трех вариантов -A
/--after-context
, -B
/--before-context
и -C
/--context
, очень близкие друг другу по смыслу, также близки друг другу по смыслу. алфавит. Это семантика?
Чтобы продолжить это и получить точный ответ, вы можете выполнить поиск применимых стандартов, таких как POSIX.1 -2008 . Кажется крайне неправдоподобным, что он запрещает бессмысленно названные опции, но я полагаю, что вам нужно внимательно прочитать все это, чтобы быть уверенным. Беглый поиск не выявляет требования, чтобы опции что-либо значили. В частности, эти официальные рекомендации--требуются только для команд, чья документация заявляет о соответствии им --рекомендуются различные ограничения на то, как могут быть названы опции и эффект от их передачи, но они не упоминают ничего, что могло бы следует интерпретировать как требование или рекомендацию о том, что имена опций имеют смысл. Даже если вы что-то нашли, многие Unix -подобные системы не стремятся к полному соответствию POSIX...
Но весь этот ход мыслей --обращения к официальным источникам, чтобы определить, (поставщики должны притворяться, что )название каждой опции что-то означает --, довольно глупо. Самое полезное, что нужно знать об опциях, это то, что их имена могут относиться друг к другу множеством способов. Они могут быть названы по словам, по другим вариантам,или для алфавитной близости к другим вариантам. Иногда это просто буква (или цифра ), которые оказались доступны. Размышление об этих способах может помочь вам запомнить параметры, найти параметры при поиске на справочных страницах и принять правильное решение о том, какие имена параметров должны использоваться вашими собственными сценариями или программами.
И последнее замечание: полезно иметь в виду, что не только краткие -формы опции могут быть названы таким образом, что это не позволит вам сделать вывод об их значении. Например, параметры длинной формы -от --regex
и от --regexp
доmlocate
называются семантически в том смысле, что они оба имеют отношение к регулярным выражениям. Но в их названии нет ничего, что говорило бы вам о том, что --regexp
означает, что следующий аргумент является BRE , а --regex
означает все аргументы шаблона. являются ЭРЭ с.
у вас есть ошибка в коде awk, вы сначала печатаете измененное значение $4 плюс полную строку
Правильный вариант такой:awk -F"|" 'NR<=1{print $0;next} {{printf($1"|" $2"|"$3"|%.2f|"$5"|"$6"\n",$4)}}' test
$ awk -F"|" 'NR<=1{print $0;next} {{printf($1"|" $2"|"$3"|%.2f|"$5"|"$6"\n",$4)}}' test
bank|Branch|Comment|Amount|Extra1|Extra2
xyz|we||100,00||
xyz|we||100,00||
xyz|we|paid for inv# 34VM23-SEP-20|23459900,00||
xyz|errt||-230,00||
xyz|ss||234,00||
xyz|we|valid|990,00||
xyz|we|9922.9 paid|9922,00||
xyz|we||0,00||
xyz|we||0,00||
xyz|we||0,00||
вам нужно напечатать все поля нетронутыми плюс поле 4, измененное по вашему желанию. Чтобы не обрабатывать первую строку, вы проверяете NR и просто печатаете строку без изменений и продолжаете с next
до второй строки
отредактировать у меня может быть проблема с моей версией awk, потому что исходная команда и моя версия не сохраняют десятичные числа, если они есть, и устанавливаю их в 0. Я думаю, это должно работать для вас. Что-то, связанное с моими МЕСТНЫМИ, я думаю. например 234.78
превращается в 234,00
на моей машине.
Еще одно решение из комментарияPaul _Pedantсостоит в том, чтобы изменить значение $4 напрямую и вывести после:
plonky@sd-143012:~/work$ awk -F '|' '{ {OFS=FS} if (FNR > 1) $4 = sprintf ("%.2f", $4); print; }' test
bank|Branch|Comment|Amount|Extra1|Extra2
xyz|we||100,00||
xyz|we||100,00||
xyz|we|paid for inv# 34VM23-SEP-20|23459900,00||
xyz|errt||-230,00||
xyz|ss||234,00||
xyz|we|valid|990,00||
xyz|we|9922.9 paid|9922,00||
xyz|we||0,00||
xyz|we||0,00||
xyz|we||0,00||
Примерно так должно работать:
awk -F '|' 'FNR>1 {printf "%s|%s|%s|%.2f|%s|%s\n", $1,$2,$3,$4,$5,$6}'
-F '|'
у вас уже есть, но это разделитель полей.
Вы сказали, что хотите пропустить первую строку, это можно сделать с помощью FNR>1
. FNR
— номер входной записи в текущем входном файле. Поскольку awk является построчным считывателем, >1
произносит процесс после первой строки .
Использование printf
также правильно, но ваш синтаксис не соответствует желаемому результату. Вы можете расширить, чтобы напечатать всю строку по запросу.
Вы также забыли возврат строки \n
в конце строки,вот почему у вас странная планировка.
с использованием Раку (урожденная Perl6)
Я бы, вероятно, сделал что-то чрезвычайно механическое, используя Raku, с явными вызовами split
и join
. Таким образом, вы можете перейти на другой разделитель столбцов (, например. запятая )с использованием той же цифры -код форматирования:
~$ raku -e 'for lines.skip(1) {my @a =.split("|");.subst(@a[3], sprintf( "%.2f", @a[3] )).join("|").put };'
Кроме того, я написал код для создания файла tmp
, который сначала содержит заголовок, а затем добавляет отформатированные строки данных. Не то, что вы просили --, но это работает. Кроме того, с этим кодом нет необходимости знать общее количество столбцов в строке (за пределами столбца, который вы пытаетесь отформатировать ).
Собираем все воедино:
~$ raku -e '.say for lines[0];' < bank.txt > tmp
~$ raku -e 'for lines.skip(1) {my @a =.split("|");.subst(@a[3], sprintf( "%.2f", @a[3] )).join("|").put };' < bank.txt >> tmp
Выход:
Bank|Branch|Comment|Amount|Extra1|Extra2
xyz|we||100.00||
xyz|we||100.10||
xyz|we|paid for inv# 34VM23-SEP-20|23459900.00||
xyz|errt||-230.00||
xyz|ss||234.78||
xyz|we|valid|990.20||
xyz|we|9922.90 paid|9922.9||
xyz|we||0.90||
xyz|we||0.00||
xyz|we||0.00||
ХТН.