Если это - все, в чем Вы нуждаетесь, просто используете free
:
$ free -h | gawk '/Mem:/{print $2}'
7.8G
free
информация о памяти возвратов, -h
переключатель говорит этому печатать в человекочитаемом формате.
Это должно сработать:
printf "one\ntwo\n" | awk 'NR>1{print PREV} {PREV=$0} END{printf("%s",$0)}' ; echo " done"
Сценарий всегда печатает предыдущую строку вместо текущей, а последняя строка обрабатывается по-другому.
Что он делает более подробно:
NR>1{печать PREV}
Печать предыдущей строки (кроме первой). {PREV=$0}
Хранит текущую строку в переменной PREV
. END{printf("%s",$0)}
Наконец, выведите последнюю строку без разрыва. Также обратите внимание, что это удалит максимум одну пустую строку в конце (отсутствует поддержка удаления "one\ntwo\n\n\n"
).
Можно использовать perl
без chomp
:
$ printf "one\ntwo\n" | perl -0 -pe 's/\n\Z//'; echo " done"
one
two done
$ printf "one\ntwo" | perl -0 -pe 's/\n\Z//'; echo " done"
one
two done
Но почему бы не использовать chomp
самому:
$ printf "one\ntwo\n" | perl -pe 'chomp if eof'; echo " done"
Если вам нужен точный эквивалент chomp
, то первым методом, который приходит мне на ум, является awk решение, которое уже размещено на LatinSuD. Я добавлю некоторые другие методы, которые не реализуют chomp
, но реализуют некоторые общие задачи, для которых часто используется chomp
.
Когда вы запихиваете какой-то текст в переменную, все новые строки в конце удаляются. Таким образом, все эти команды выдают один и тот же однострочный вывод:
echo "$(printf 'one\ntwo') done"
echo "$(printf 'one\ntwo\n') done"
echo "$(printf 'one\ntwo\n\n') done"
echo "$(printf 'one\ntwo\n\n\n\n\n\n\n\n\n\n') done"
Если Вы хотите добавить какой-то текст в последнюю строку файла или вывода команды, sed
может быть удобно. В GNU sed и большинстве других современных реализаций это работает, даже если ввод не заканчивается на новую строку¹; однако это не добавит новую строку, если ее уже не было.
sed '$ s/$/ done/'
¹ Однако это работает не со всеми реализациями sed: sed - это текстовое средство обработки, а файл, который не пуст и не заканчивается на символ новой строки, не является текстовым файлом.
Другой перл
подход. Этот подход считывает все входные данные в память, так что это может быть не очень хорошей идеей для больших объемов данных (используйте для этого подход cuonglm's или awk
):
$ printf "one\ntwo\n" | perl -0777pe 's/\n$//'; echo " done"
one
two done
#реферат
Печатать строки без новой строки, добавлять новую строку, только если есть еще одна строка для печати.
$ printf 'one\ntwo\n' |
awk '{ printf( "%s%s", NR>1?"\n":"", $0 ) }'; echo " done"
one
two done
#Другие решения Если бы мы работали с файлом, мы могли бы просто обрезать из него один символ (, если он заканчивается на новой строке):
removeTrailNewline(){ [[ $(tail -c 1 "$1") ]] || truncate -s-1 "$1"; }
Это быстрое решение, так как нужно прочитать только один символ из файла, а затем удалить его напрямую(truncate
)без чтения всего файла.
Однако при работе с данными из стандартного ввода (потока )данные должны быть прочитаны целиком. И он «потребляется», как только он прочитан. Без возврата (, как с усечением ). Чтобы найти конец потока, нам нужно прочитать до конца потока. В этот момент нет возможности вернуться к входному потоку, данные уже «израсходованы». Это означает, что данные должны храниться в некотором буфере до тех пор, пока мы не совпадем с концом потока, а затем что-то сделать с данными в буфере.
Наиболее очевидным решением является преобразование потока в файл и обработка этого файла. Но вопрос требует какого-то фильтра потока. Не об использовании дополнительных файлов.
###переменная Наивным решением было бы записать весь ввод в переменную :
.FilterOne(){ filecontents=$(cat; echo "x"); # capture the whole input
filecontents=${filecontents%x}; # Remove the "x" added above.
nl=$'\n'; # use a variable for newline.
printf '%s' "${filecontents%"$nl"}"; # Remove newline (if it exists).
}
printf 'one\ntwo' | FilterOne ; echo 1done
printf 'one\ntwo\n' | FilterOne ; echo 2done
printf 'one\ntwo\n\n' | FilterOne ; echo 3done
###память С помощью sed можно загрузить в память целый файл. В sed невозможно избежать завершающей новой строки в последней строке. GNU sed может не печатать завершающую новую строку, но только если в исходном файле она уже отсутствует. Так что нет, простой sed не может помочь.
За исключением GNU awk с опцией -z
:
sed -z 's/\(.*\)\n$/\1/'
С помощью awk (любой awk ), slurp весь поток, и printf
без завершающей новой строки.
awk ' { content = content $0 RS }
END { gsub( "\n$", "", content ); printf( "%s", content ) }
'
Загрузка всего файла в память может быть плохой идеей, так как это может занять много памяти.
###Две строчки в памяти В awk мы можем обрабатывать две строки за цикл, сохраняя предыдущую строку в переменной и выводя текущую :
.awk 'NR>1{print previous} {previous=$0} END {printf("%s",$0)}'
###Прямая обработка Но мы могли бы сделать лучше.
Если мы печатаем текущую строку без новой строки и печатаем новую строку только тогда, когда существует следующая строка, мы обрабатываем одну строку за раз, и последняя строка не будет не иметь завершающую новую строку:
awk 'NR==1{ printf ("%s",$0 );далее }; { printf ("\n%s", $0 )}'
Или как-нибудь иначе:
awk 'NR>1{ print "" }; { printf( "%s", $0 ) }'
Или:
awk '{ printf( "%s%s", NR>1?"\n":"", $0 ) }'
Так:
$ printf 'one\ntwo\n' | awk '{ printf( "%s%s", NR>1?"\n":"", $0 ) }'; echo " done"
one
two done
Я взял это где-то из репозитория github, но не могу найти, где
#!/bin/bash
#
# Delete all trailing blank lines.
# From http://sed.sourceforge.net/sed1line.txt
#
# Version: 1.3.0
# Created: 2011-01-02
# Updated: 2015-01-25
# Contact: Joel Parker Henderson (joel@joelparkerhenderson.com)
# License: GPL
##
set -euf
sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'
Я обнаружил, что bash может делать то, что я хотел, без каких-либо других инструментов. Это не будет точно воспроизводить chomp
, но может кому-то помочь.
Команда, вывод которой заканчивается символом новой строки, будет перехвачена при подстановке:
the_output=$(my_command_with_a_newline)
Его можно использовать как часть конвейера сecho -n
(кавычками замены, чтобы сохранить другие новые строки):
echo -n "$(my_command_with_a_newline)" |tail_or_whatever
Использование printf "one\ntwo\n"
аналогично OP:
$ echo -n "$(printf "one\ntwo\n")"; echo " done"
one
two done