Получение первых [x] символов для строки из канала

58

Если у меня действительно длинный вывод команды (в одну строку), но я знаю, что мне нужны только первые [x] (скажем, 8) символы вывода, какой самый простой способ получить это? Здесь нет разделителей.

xenoterracide
источник
связанные: stackoverflow.com/questions/1405611/…
Сиро Сантилли 新疆 改造 中心 法轮功 六四 事件

Ответы:

82

Одним из способов является использование cut:

 command | cut -c1-8

Это даст вам первые 8 символов каждой строки вывода. Так как cutявляется частью POSIX, он, вероятно, будет в большинстве Unices.

Стивен Д
источник
3
Обратите внимание, что cut -cвыбирает символы; cut -bили head -cвыбирает байты. Это имеет значение в некоторых локалях (на практике, при использовании UTF-8).
Жиль "ТАК - перестать быть злым"
Вам также не нужно указывать начальный индекс в этом случае. Поговорка cut -c-8будет выбирать из символов от 1 до 8.
Sparhawk
@ Steven, cutэквивалент на Windows есть?
Pacerier
Также command | dd bs=8 count=1 2>/dev/null. Не говоря, что это короче или выше. Просто другая альтернатива.
dubiousjim
@Gilles, но обратите внимание , что с текущей версией GNU cut, cut -cработает как cut -b(то есть, он не работает должным образом для многобайтных символов).
Стефан Шазелас
24

Это еще несколько способов получить только первые 8 символов.

command | head -c8

command | awk '{print substr($0,1,8);exit}' 

command | sed 's/^\(........\).*/\1/;q'

И если у вас есть Баш

var=$(command)
echo ${var:0:8}
user1606
источник
2
Я думаю , что следующая формулировка СЭД немного легче читать: command | sed 's/\(.\{8\}\).*/\1/'или если ваш SED поддерживает его: command | sed -r 's/(.{8}).*/\1/'; В противном случае +1
Стивен Д.
Хорошие вещи, но обратите внимание, что head -cучитываются байты , а не символы. Аналогично, среди основных реализаций Awk только GNU awk правильно обрабатывает многобайтовые символы, а FreeBSD Awk и Mawk - нет.
mklement0
2

Если у вас достаточно продвинутая оболочка (например, в Bash будет работать следующее, но вы не уверены в dash), вы можете сделать следующее:

read -n8 -d$'\0' -r <(command)

После выполнения read ... <(command)ваши символы будут находиться в переменной оболочки REPLY. Введите, help readчтобы узнать о других вариантах.

Объяснение: -n8аргумент to readговорит, что мы хотим до 8 символов. -d$'\0'Говорит чтение до нуля, а не перевод строки. Таким образом, чтение будет продолжаться в течение 8 символов, даже если один из более ранних символов является новой строкой (но не если это нулевое значение). Альтернативой -n8 -d$'\0'является использование -N8, которое читает ровно 8 символов или до тех пор, пока стандартный ввод не достигнет EOF. Никакой разделитель не приветствуется. Это, вероятно, лучше соответствует вашим потребностям, но я не знаю, сколько снарядов имеет чтение, которое чтит, -Nа не чтит -nи -d. Продолжая объяснение: -rговорит игнорировать \-escapes, так что, например, мы рассматриваем \\как два символа, а не как один \.

Наконец, мы делаем, read ... <(command)а не command | read ...потому, что во второй форме чтение выполняется в подоболочке, которая затем немедленно завершается, теряя информацию, которую вы только что прочитали.

Другой вариант - выполнить всю обработку внутри subshell. Например:

$ echo abcdefghijklm | { read -n8 -d$'\0' -r; printf "REPLY=<%s>\n" "$REPLY"; }
REPLY=<abcdefgh>
dubiousjim
источник
1
Если вы просто хотите вывести 8 символов и не нужно обрабатывать их в оболочке, просто используйте cut.
dubiousjim
Полезно знать о read -n <num>; небольшое предостережение: Bash 3.x (все еще актуальный в ОС) по ошибке интерпретируется <num>как число байтов и, таким образом, завершается с многобайтовыми символами; это было исправлено в Bash 4.x.
mklement0
Это отличный и полезный ответ. Гораздо более общий, чем другие.
not2qubit
2

Еще одно линейное решение с использованием расширения параметров

echo ${word:0:x}

EG: word="Hello world"
echo ${word:0:3} or echo ${word::3} 
o/p: Hel


EG.2: word="Hello world"
echo ${word:1:3}
o/p: ell
Прабхат Кумар Сингх
источник
Вы также можете использовать переменную, содержащую длину, например: x=8; echo ${word:0:$x}вместо жесткого кодирования целого числа.
Cometsong
1

Это портативный:

a="$(command)"             # Get the output of the command.
b="????"                   # as many ? as characters are needed.
echo ${a%"${a#${b}}"}      # select that many chars from $a

Для построения строки переменной длины символов здесь есть свой вопрос .

Сообщество
источник
0

У меня была эта проблема при создании файлов контрольной суммы вручную в репозитории maven. К сожалению, cut -cвсегда выводит новую строку в конце вывода. Для подавления того, что я использую xxd:

command | xxd -l$BYTES | xxd -r

Он выводит ровно $BYTESбайты, если commandвыходной результат не короче, то именно этот вывод.

Кшиштоф Яблонский
источник
Другой способ снять cut| tr -d '\n'
конечную новую строку