bash - файл - linux перенаправление вывода в dev null




Как установить переменную на вывод команды в Bash? (9)

Некоторые трюки bash которые я использую для установки переменных из команд

2nd Edit 2018-02-12: Добавляя особый путь, см. В самом низу этого!

2018-01-25 Edit: добавьте функцию образца (для заполнения vars о дисках)

Первый простой старый и совместимый способ

myPi=`echo '4*a(1)' | bc -l`
echo $myPi 
3.14159265358979323844

В основном совместимый, второй способ

Поскольку вложенность может стать тяжелой, для этой

myPi=$(bc -l <<<'4*a(1)')

Вложенный образец:

SysStarted=$(date -d "$(ps ho lstart 1)" +%s)
echo $SysStarted 
1480656334

чтение более одной переменной (с бахизмами )

df -k /
Filesystem     1K-blocks   Used Available Use% Mounted on
/dev/dm-0         999320 529020    401488  57% /

Если я просто хочу Использованное значение:

array=($(df -k /))

вы можете увидеть переменную массива :

declare -p array
declare -a array='([0]="Filesystem" [1]="1K-blocks" [2]="Used" [3]="Available" [
4]="Use%" [5]="Mounted" [6]="on" [7]="/dev/dm-0" [8]="999320" [9]="529020" [10]=
"401488" [11]="57%" [12]="/")'

Затем:

echo ${array[9]}
529020

Но я предпочитаю это:

{ read foo ; read filesystem size used avail prct mountpoint ; } < <(df -k /)
echo $used
529020

1st read foo просто пропустит строку заголовка (переменная $foo будет содержать что-то вроде Filesystem 1K-blocks Used Available Use% Mounted on )

Пример функции для заполнения некоторых переменных:

#!/bin/bash

declare free=0 total=0 used=0

getDiskStat() {
    local foo
    {
        read foo
        read foo total used free foo
    } < <(
        df -k ${1:-/}
    )
}

getDiskStat $1
echo $total $used $free

Nota: строка declare не требуется, просто для удобства чтения.

О sudo cmd | grep ... | cut ... sudo cmd | grep ... | cut ...

shell=$(cat /etc/passwd | grep $USER | cut -d : -f 7)
echo $shell
/bin/bash

(Пожалуйста, избегайте бесполезной cat ! Так что это всего лишь 1 вилка меньше:

shell=$(grep $USER </etc/passwd | cut -d : -f 7)

Все трубы ( | ) подразумевают вилки. Там, где должен выполняться другой процесс, доступ к дискам, вызовам библиотек и т. Д.

Поэтому использование sed для образца ограничивает подпроцесс только одной вилкой :

shell=$(sed </etc/passwd "s/^$USER:.*://p;d")
echo $shell

И с багизмами :

Но для многих действий, в основном на небольших файлах, bash мог выполнить эту работу сам:

while IFS=: read -a line ; do
    [ "$line" = "$USER" ] && shell=${line[6]}
  done </etc/passwd
echo $shell
/bin/bash

или же

while IFS=: read loginname encpass uid gid fullname home shell;do
    [ "$loginname" = "$USER" ] && break
  done </etc/passwd
echo $shell $loginname ...

Далее о переменном расщеплении ...

Посмотрите на мой ответ: Как разбить строку на разделителе в Bash?

Альтернатива: сокращение вилок с использованием фоновых длительных задач

2-е изм. Редактирование 2018-02-12: Чтобы предотвратить появление нескольких вилок

myPi=$(bc -l <<<'4*a(1)'
myRay=12
myCirc=$(bc -l <<<" 2 * $myPi * $myRay ")

или же

myStarted=$(date -d "$(ps ho lstart 1)" +%s)
mySessStart=$(date -d "$(ps ho lstart $$)" +%s)

И поскольку date и bc могут работать по строкам :

bc -l <<<$'3*4\n5*6'
12
30

date -f - +%s < <(ps ho lstart 1 $$)
1516030449
1517853288

Мы могли бы использовать длительный фоновый процесс для повторной работы, без необходимости запуска новой вилки для каждого запроса:

mkfifo /tmp/myFifoForBc
exec 5> >(bc -l >/tmp/myFifoForBc)
exec 6</tmp/myFifoForBc
rm /tmp/myFifoForBc

(конечно, FD 5 и 6 должны быть неиспользованными!) ... Оттуда вы можете использовать этот процесс:

echo "3*4" >&5
read -u 6 foo
echo $foo
12

echo >&5 "pi=4*a(1)"
echo >&5 "2*pi*12"
read -u 6 foo
echo $foo
75.39822368615503772256

В функцию newConnector

Вы можете найти мою функцию newConnector на GitHub.Com или на моем собственном сайте (Nota on github, есть два файла, на моем сайте, функция и демонстрация включены в 1 файл, который может быть использован для использования или просто запускаться для демонстрации)

Образец:

. shell_connector.sh

tty
/dev/pts/20

ps --tty pts/20 fw
    PID TTY      STAT   TIME COMMAND
  29019 pts/20   Ss     0:00 bash
  30745 pts/20   R+     0:00  \_ ps --tty pts/20 fw

newConnector /usr/bin/bc "-l" '3*4' 12

ps --tty pts/20 fw
    PID TTY      STAT   TIME COMMAND
  29019 pts/20   Ss     0:00 bash
  30944 pts/20   S      0:00  \_ /usr/bin/bc -l
  30952 pts/20   R+     0:00  \_ ps --tty pts/20 fw

declare -p PI
bash: declare: PI: not found

myBc '4*a(1)' PI
declare -p PI
declare -- PI="3.14159265358979323844"

Функция myBc позволяет использовать фоновое задание с простым синтаксисом и для даты:

newConnector /bin/date '-f - +%s' @0 0
myDate '2000-01-01'
  946681200
myDate "$(ps ho lstart 1)" boottime
myDate now now ; read utm idl </proc/uptime
myBc "$now-$boottime" uptime
printf "%s\n" ${utm%%.*} $uptime
  42134906
  42134906

ps --tty pts/20 fw
    PID TTY      STAT   TIME COMMAND
  29019 pts/20   Ss     0:00 bash
  30944 pts/20   S      0:00  \_ /usr/bin/bc -l
  32615 pts/20   S      0:00  \_ /bin/date -f - +%s
   3162 pts/20   R+     0:00  \_ ps --tty pts/20 fw

Оттуда, если вы хотите закончить один из фоновых процессов, вам просто нужно закрыть его fd :

eval "exec $DATEOUT>&-"
eval "exec $DATEIN>&-"
ps --tty pts/20 fw
    PID TTY      STAT   TIME COMMAND
   4936 pts/20   Ss     0:00 bash
   5256 pts/20   S      0:00  \_ /usr/bin/bc -l
   6358 pts/20   R+     0:00  \_ ps --tty pts/20 fw

которые не нужны, потому что все fd закрываются при завершении основного процесса.

У меня довольно простой скрипт, который выглядит примерно так:

#!/bin/bash

VAR1="$1"    
MOREF='sudo run command against $VAR1 | grep name | cut -c7-'

echo $MOREF

Когда я запускаю этот скрипт из командной строки и передаю ему аргументы, я не получаю никакого вывода. Однако, когда я запускаю команды, содержащиеся в переменной $MOREF , я могу получить выход.

Я хотел бы знать, как можно взять результаты команды, которая должна выполняться в скрипте, сохранить его в переменной и затем выводить эту переменную на экран?


В дополнение к backticks ( `command` ) вы можете использовать $(command) , которую мне легче читать, и позволяет вложенность.

OUTPUT="$(ls -1)"
echo "${OUTPUT}"

Цитирование ( " ) имеет значение для сохранения многострочных значений.


Вы должны использовать либо

$(command-here)

или же

`command-here`

пример

#!/bin/bash

VAR1="$1"
VAR2="$2"

MOREF="$(sudo run command against "$VAR1" | grep name | cut -c7-)"

echo "$MOREF"

Вы можете использовать обратные тики (также известные как ударные могилы) или $() . Как-

OUTPUT=$(x+2);
OUTPUT=`x+2`;

Оба имеют тот же эффект. Но OUTPUT = $ (x + 2) является более читаемым и последним.


Как они уже указывали вам, вы должны использовать «обратные сигналы».

Альтернативная предложенная $(command) работает, и ее также легче читать, но обратите внимание, что она действительна только с оболочками bash или korn (и оболочками, полученными из них), поэтому, если ваши скрипты должны быть действительно переносимыми на разных Unix систем, вы должны предпочесть старую обратную запись.


Некоторые могут найти это полезным. Целочисленные значения в подстановке переменных, где трюк использует двойные скобки $(()) :

N=3
M=3
COUNT=$N-1
ARR[0]=3
ARR[1]=2
ARR[2]=4
ARR[3]=1

while (( COUNT < ${#ARR[@]} ))
do
  ARR[$COUNT]=$((ARR[COUNT]*M))
  (( COUNT=$COUNT+$N ))
done

Просто быть другим:

MOREF=$(sudo run command against $VAR1 | grep name | cut -c7-)

Это еще один способ, который можно использовать с некоторыми текстовыми редакторами, которые не могут правильно выделить каждый сложный код, который вы создаете.

read -r -d '' str < <(cat somefile.txt)
echo "${#str}"
echo "$str"

Обновление (2018): правильный путь

$(sudo run command)

Вы используете неправильный апостроф. Вам нужно ` , а не ' . Этот символ называется «backticks» (или «серьезным акцентом»).

Как это:

#!/bin/bash

VAR1="$1"
VAR2="$2"

MOREF=`sudo run command against "$VAR1" | grep name | cut -c7-`

echo "$MOREF"




command-line