Пропуск первой строки файла

Если вы переводите машину с двойной загрузкой в спящий режим, отмонтируйте все общие разделы. Убедитесь, что спящий режим завершится неудачно, если какой-либо из общих разделов не может быть размонтирован.

Вы можете немного смягчить правила и установить одну из ОС в качестве "владельца" общего раздела при следующих условиях:

  • Только владелец монтирует раздел в режиме чтения-записи. Другие ОС монтируют его только на чтение.
  • При выводе владельца из спящего режима перемонтируйте раздел только для чтения.

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

Примечание: остерегайтесь монтировать раздел, который используется спящей системой, даже если вы монтируете его только для чтения. Например, при монтировании только для чтения файловой системы ext4, которая не была чисто размонтирована (что происходит, если она используется системой, находящейся в спящем режиме), происходит повторное создание журнала и запись на диск, что нарушает работу системы, находящейся в спящем режиме. Вызовите mount -o ro,noload для монтирования файловой системы ext4, смонтированной в режиме чтения-записи в системе, находящейся в спящем режиме.


Если вы не хотите загружать другие ОС, пока одна из них находится в спящем режиме, это возможно: организуйте скрипты гибернации так, чтобы они изменяли настройки загрузчика. Как именно это сделать, зависит от того, какие ОС вы используете и какова конфигурация вашего загрузчика. Для Grub достаточно переписать файл grub.cfg: когда вы переводите систему S в спящий режим, создайте grub.cfg только с одним пунктом меню для возобновления работы системы S; когда S выходит из спящего режима, восстановите grub.cfg с несколькими вариантами.

1
06.02.2019, 08:07
2 ответа

Вы только что допустили опечатку в последней строке вашего awk-скрипта. :В адресе:

должно быть FNRвместо FR.
BEGIN { CONVFMT="%0.17f" }

function t(n, s) {
   s=index(n,".")
   return (s ? substr(n,1,s+2) : n)
}

FNR>1 {print t($1-1000),t($2)}

Это работает, как и ожидалось.

При опечатке адрес FR>1не соответствует ни одной из ваших строк данных:FRявляется константой и условие FR>1всегда ложно. Вот почему вы не получаете никакого вывода.

1
28.04.2021, 23:37

Есть несколько способов пропустить первую строку.

NR>1{ … }            # For every record after the first.
BEGIN{ getline }     # Only on the start, read the first line
!var{var=1;next}     # If var is unset, set it and skip one line.
FNR>1{ … }           # For records after the first for every file listed.

Переменная NRозначает «Номер записи», и, предполагая, что разделитель записи по умолчанию (используется новая строка ), это также номер каждой строки. Первая строка (в этом случае )имеет номер 1. Если NRбольше, чем 1, то то, что выполняется внутри фигурной скобки, выполняется только после первой строки.

Вместо этого переменная FNRозначает, что номер записи сбрасывается до нуля для каждого файла, указанного в командной строке(awk 'script' file1 file2 filen …). Что в точности эквивалентно NR>1, но сбрасывается для каждого нового файла.

Функция обрезки

Кроме того, у вас есть определение функции для t(n,s), которое нацелено на (в соответствии с вашим комментарием )«урезать число до 2 знаков после запятой», но оно делает это неправильно.

В этом определении функции есть команда, которая находит точку. Предполагается, что точка является десятичным разделителем:

s=index(n,".")

А затем (как строка )обрезает строку для поля через два символа после точки. Это для числа без показателя степени правильно работает для обрезки десятичных знаков, но число использует показатель степени, например 1.2345678e3. Он будет обрезан до 1.23. Это, конечно, не то же самое, что правильное усечение до двух знаков после запятой, как 1234.56.

Чтобы правильно обрезать число, необходимо учитывать показатель степени. Функция intделает именно это:

function ti(n){ return( int(100*n)/100 ) }

Но вы можете лучше полагаться на аппроксимацию, применяемую к числам с плавающей запятой:

function tf(n){ return( sprintf( "%.2f",n ) ) }

Они различаются количеством аппроксимации (на самом деле, тип )каждый делает.Функция, использующая int, округляет в сторону нуля до меньшего целого числа (для положительного числа ). Для числа, подобного 3.7, оно в любом случае округляется до 3, ошибка 0.7. Функция с числом float округляется до ближайшего целого числа. Максимальная ошибка 0.5. Число, указанное выше, например 3.7, округляется до 4, ошибка составляет только 0.3. Итак, один — округление до нулевого приближения, другой — округление до ближайшего целого числа . У одного может быть максимальная ошибка 0.9, у другого только 0.5. Единственная странность в плавающем приближении состоит в том, что оно иногда 0.5округляет в большую сторону, а иногда 0.5в меньшую. Это предназначено для балансировки раундов вверх и вниз.

Понятно, что 0,1, 0,2, 0,3 и 0,4 нужно округлить до 0.
Это приводит к ошибкам 0,1, 0,2, 0,3 и 0,4.
Вместо 0,9, 0,8. 0,7 и 0,6 округлить до 1.
Это приводит к ошибке -0,1, -0,2, -0,3, -0,4

Все эти ошибки (в среднем для случайного ввода )уравновешиваются.

Но если мы всегда округляем 0,5 в большую сторону, возникает постоянная ошибка 0,5.

Чтобы сбалансировать это, один раз мы округляем в меньшую сторону, затем округляем в большую.
Или, как обычно пишут:круглые связи (0.5 )с четными .

printf '%s ' $l; echo; printf '%-3.0f ' $l; echo
0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 
0   0   0   0   0   1   1   1   1   1   1   1   1   1   2   2   2   2   2   2

Обратите внимание, что 0.5округляется до0(в меньшую сторону ), а 1.5округляется до2(в большую)

Точность

Вы должны использовать CONVFMT="%.16g"в качестве формата для преобразования чисел с плавающей запятой.

Формат fбудет обрезать значащие цифры, например:

$ awk 'BEGIN{var=1.23456789e-8;printf "%.9f\n",var}'
0.000000012

Только две значащие цифры. Вместо этого формат g:

$ awk 'BEGIN{var=1.23456789e-8;printf "%.9f\n",var}'
1.23456789e-08

Сохранит 9 значащих цифр (цифры ).

Имя файла

Это полезно для команд awk, которые применяются к нескольким файлам, например:

$ awk 'FNR>1{print $1}' file1 file2 file3

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

1
28.04.2021, 23:37

Теги

Похожие вопросы