Как я могу удалить запаздывающую новую строку в ударе?

Если это - все, в чем Вы нуждаетесь, просто используете free:

$ free -h | gawk  '/Mem:/{print $2}'
7.8G

free информация о памяти возвратов, -h переключатель говорит этому печатать в человекочитаемом формате.

9
22.07.2015, 15:33
7 ответов

Это должно сработать:

printf "one\ntwo\n" | awk 'NR>1{print PREV} {PREV=$0} END{printf("%s",$0)}' ; echo " done"

Сценарий всегда печатает предыдущую строку вместо текущей, а последняя строка обрабатывается по-другому.

Что он делает более подробно:

  1. NR>1{печать PREV} Печать предыдущей строки (кроме первой).
  2. {PREV=$0} Хранит текущую строку в переменной PREV.
  3. END{printf("%s",$0)} Наконец, выведите последнюю строку без разрыва.

Также обратите внимание, что это удалит максимум одну пустую строку в конце (отсутствует поддержка удаления "one\ntwo\n\n\n").

8
27.01.2020, 20:04

Можно использовать 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"
14
27.01.2020, 20:04

Если вам нужен точный эквивалент 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 - это текстовое средство обработки, а файл, который не пуст и не заканчивается на символ новой строки, не является текстовым файлом.

4
27.01.2020, 20:04

Другой перл подход. Этот подход считывает все входные данные в память, так что это может быть не очень хорошей идеей для больших объемов данных (используйте для этого подход cuonglm's или awk):

$ printf "one\ntwo\n" | perl -0777pe 's/\n$//'; echo " done"
one
two done
1
27.01.2020, 20:04

#реферат

Печатать строки без новой строки, добавлять новую строку, только если есть еще одна строка для печати.

$ 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
0
27.01.2020, 20:04

Я взял это где-то из репозитория github, но не могу найти, где

удалить -конечные -пустые -строки -sed

#!/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 '}'
0
27.01.2020, 20:04

Я обнаружил, что 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
1
03.08.2020, 07:20

Теги

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