Из spec :
bs =
expr
и никаких преобразований кроме ] sync
, noerror
или notrunc
запрашиваются, данные, возвращаемые из каждого входного блока, должны быть записаны как отдельный выходной блок; если read ()
возвращает меньше, чем полный блок, а преобразование sync
не указано, результирующий выходной блок должен быть того же размера, что и входной блок. Так что, вероятно, это и вызывает ваше замешательство. Да, поскольку dd
предназначен для блокировки, по умолчанию частичные read ()
будут сопоставлены 1: 1 с частичным write ()
s, или sync
d на завершающем заполнении NUL или пробелами до размера bs =
, если задано conv = sync
.
Это означает, что dd
безопасен для копирования данных (без риска повреждения из-за частичного чтения или записи) во всех случаях, кроме одного, в котором он произвольно ограничено аргументом count =
, потому что в противном случае dd
с радостью write ()
его вывод в блоках одинакового размера с теми, в которых его вводом было read ()
, пока он не прочитает ()
полностью через него. И даже это предупреждение верно только , когда указано bs =
или obs =
не указано , как следующее предложение в В спецификации указано:
bs =
expr
не указан, или преобразование, отличное от sync
, noerror
или notrunc
, ввод должен быть обработан и собран в полноразмерные блоки вывода до тех пор, пока не будет достигнут конец ввода. Без аргументов ibs =
и / или obs =
это не имеет значения, потому что ibs
и obs
одинаковы размер по умолчанию. Однако вы можете получить явное о буферизации ввода, указав разных размеров для любого и не , указав bs =
(потому что это имеет приоритет) .
Например, если вы это сделаете:
IN| dd ibs=1| OUT
...тогда POSIX dd
будет write ()
кусками по 512 байт, собирая каждый отдельный байт read ()
в один выходной блок .
В противном случае, если вы сделаете ...
IN| dd obs=1kx1k| OUT
... POSIX dd
будет read ()
максимум 512 байт за раз, но ] write ()
каждый выходной блок размером в мегабайт (ядро разрешает и, возможно, исключая последний - потому что это EOF) полностью, собирая входные данные в полноразмерных выходных блоков .
Также из спецификации:
count = n
count =
отображается на i? Bs =
блоков,и поэтому для обработки произвольного ограничения на count =
переносимо вам понадобятся два dd
s. Наиболее практичный способ сделать это с двумя dd
s - связать вывод одного с вводом другого, что, безусловно, помещает нас в сферу чтения / записи специального файла независимо от исходного типа ввода.
Канал IPC означает, что при указании [io] bs =
аргументов, чтобы сделать это безопасно, вы должны сохранить такие значения в пределах установленного системой ограничения PIPE_BUF
. POSIX утверждает, что ядро системы должно гарантировать только атомарные read ()
и write ()
s в пределах PIPE_BUF
, как определено в пределах . ч
. POSIX гарантирует, что PIPE_BUF
будет как минимум ...
{_ POSIX_PIPE_BUF}
... (которое также является размером блока ввода-вывода по умолчанию dd
по умолчанию) , но фактическое значение обычно составляет не менее 4k. В современной системе Linux это по умолчанию 64 КБ.
Итак, когда вы настраиваете свои процессы dd
, вы должны делать это с коэффициентом блока на основе трех значений:
PIPE_BUF
или меньше) Например:
yes | dd obs=1k | dd bs=1k count=10k of=/dev/null
10240+0 records in
10240+0 records out
10485760 bytes (10 MB) copied, 0.1143 s, 91.7 MB/s
Вы должны синхронизировать i / ow / dd
для обработки отсутствия поиска входы. Другими словами, сделайте буферы каналов явными, и они перестанут быть проблемой.Для этого нужен dd
. Неизвестной величиной здесь является размер буфера да
, но если вы заблокируете это до известной величины с другим dd
, то небольшое умножение на основе информации может дать dd
безопасно использовать для копирования данных (без риска повреждения из-за частичного чтения или записи) даже при произвольном ограничении ввода с count =
с любым произвольным вводом введите в любой системе POSIX и не пропустите ни одного байта.
Вот фрагмент из спецификации POSIX :
ibs =
expr
expr
(по умолчанию 512 ) . obs =
expr
expr
(по умолчанию 512) . bs =
expr
expr
байтов, заменив ibs =
и obs =
. Если не указано никакого преобразования, кроме sync
, noerror
и notrunc
, каждый входной блок должен копироваться на выход как единый блок без агрегирования коротких блоков. Вы также найдете некоторые из этих объяснений лучше здесь .
в bash, используяcolumn
$ column -s $'\t' -t file.tsv
col1 col2 col2 col2 col3 col3 col4
col1 col2 col2 col3 col4 col4
col1 col1 col2 col2 col3 col4 col4 col4
column -t
использует 2 пробела для разделения столбцов
С awk я бы написал
awk -F '\t' -v cols=4 '
NR == FNR {
for (i=1; i<=cols; i++)
if (NR == 1 || length($i) > w[i])
w[i] = length($i)
next
}
{
for (i=1; i<=cols; i++)
printf "%-*s%s", w[i], $i, (i == cols ? ORS : FS)
}
' file.tsv file.tsv
Где я обрабатываю файл дважды :сначала, чтобы найти максимальную ширину для каждого столбца, а затем еще раз, чтобы переформатировать файл. Я использую вкладку, чтобы разделить столбцы в выводе.
col1 col2 col2 col2 col3 col3 col4
col1 col2 col2 col3 col4 col4
col1 col1 col2 col2 col3 col4 col4 col4