Для тех, кто не понимает advanced awk
, а также хотел бы (например, для таких, как я) и не имеет предустановленного jq
, простым решением было бы объединение нескольких собственных команд, таких как:
grep -A2 '"id": 1490,' stats.json | sed '/1490/d;s/"//g;s/,//;s/\s*//'
Если вы пытаетесь получить только значения, проще просто использовать grep
, а не awk
или sed
:
grep -A2 '"id": 1490,' stats.json | grep -o "[0-9]*\.[0-9]*"
Чтобы дать объяснение, это кажется мне самым простым способом.
grep -A2
захватов линия, которую вы ищете в JSON, вместе со следующими линиями 2, которые содержат температуру и влажность. grep -o
просто печатает только цифры, разделенные .
(что никогда не произойдет на первой 1490
линии, поэтому вы оставлены с вашими 2 значениями - температура и влажность. Очень просто. Даже проще, чем использовать jq
, на мой взгляд. -121--32291-
Существуют два очевидных способа представления вывода столбчатых данных в JSON: массив массивов и массив объектов. В первом случае каждая строка ввода преобразуется в массив; в последнем - к объекту.
Перечисленные ниже команды работают, по крайней мере, с выходом procps-ng в Linux для команд ps
и ps -l
.
можно преобразовать выходные данные с помощью Perl и модуля CPAN JSON:: XS .
# ps | perl -MJSON -lane 'my @a = @F; push @data, \@a; END { print encode_json \@data }'
[["PID","TTY","TIME","CMD"],["12921","pts/2","00:00:00","ps"],["12922","pts/2","00:00:00","perl"],["28280","pts/2","00:00:01","zsh"]]
можно также использовать jq для преобразования.
# ps | jq -sR '[sub("\n$";"") | splits("\n") | sub("^ +";"") | [splits(" +")]]'
[
[
"PID",
"TTY",
"TIME",
"CMD"
],
[
"16694",
"pts/2",
"00:00:00",
"ps"
],
[
"16695",
"pts/2",
"00:00:00",
"jq"
],
[
"28280",
"pts/2",
"00:00:02",
"zsh"
]
]
Можно преобразовать входные данные в массив объектов JSON с значимо именованными ключами, взяв имена ключей из строки заголовка.
Это требует немного больше усилий и немного сложнее в jq в частности. Однако результат, возможно, более удобочитаем для человека.
# ps | perl -MJSON -lane 'if (!@keys) { @keys = @F } else { my %h = map {($keys[$_], $F[$_])} 0..$#keys; push @data, \%h } END { print encode_json \@data }'
[{"TTY":"pts/2","CMD":"ps","TIME":"00:00:00","PID":"11030"},{"CMD":"perl","TIME":"00:00:00","PID":"11031","TTY":"pts/2"},{"TTY":"pts/2","CMD":"zsh","TIME":"00:00:01","PID":"28280"}]
Обратите внимание, что ключи находятся в произвольном порядке для каждой записи. Это артефакт того, как работают хэши Перла.
# ps | jq -sR '[sub("\n$";"") | splits("\n") | sub("^ +";"") | [splits(" +")]] | .[0] as $header | .[1:] | [.[] | [. as $x | range($header | length) | {"key": $header[.], "value": $x[.]}] | from_entries]'
[
{
"PID": "19978",
"TTY": "pts/2",
"TIME": "00:00:00",
"CMD": "ps"
},
{
"PID": "19979",
"TTY": "pts/2",
"TIME": "00:00:00",
"CMD": "jq"
},
{
"PID": "28280",
"TTY": "pts/2",
"TIME": "00:00:02",
"CMD": "zsh"
}
]
-121--78913-
Зачем изобретать колесо заново? qprint
уже существует:
Description-en: encoder и decoder для кодировки с печатью в кавычках
Qprint - это программа командной строки, которая может кодировать или декодировать файлы кодирование с печатью в кавычках (RFC1521). Он может работать с обоими текстовые и двоичные данные.
Домашняя страница: http://www.fourmilab.ch/webtools/qprint/
Пример ввода:
$ cat nadir.txt
Hyundai ya ofrece manuales de =
los coches con Realidad Aumentada
Пример вывода:
$ qprint -d nadir.txt
Hyundai ya ofrece manuales de los coches con Realidad Aumentada
qprint
предварительно упакован для большинства distros linux.
Есть также несколько модулей жемчуга для кодирования & указанной расшифровки - пригодный для печатания текст, включая ПАНТОМИМА:: QuotedPrint
и PerlIO:: через:: QuotedPrint
. Несомненно, быстрый поиск Google также выявит библиотеки QP для питона и других языков.
Спасибо всем. И дело в разделителе. Я меняю "/" на ":" и все работает. Выкладываю результат сюда. В «Шаге 65/78» я печатаю содержимое сценария, а «Шаг 67/78» хорошо запускает сценарий. Спасибо @xenoid и @Kusalananda.
Step 63/78 : RUN echo "#!/bin/sh -x\nsed -i 's:PRIVATEIP:'"$(cat /home/ip_variable)"':g' /etc/fail2ban/jail.local\nsed -i 's:PRIVATEIP:'"$(cat /home/ip_variable)"':g' /etc/opendkim/TrustedHosts" > /home/ip_change_script.sh
---> Running in 251d6741c37e
Removing intermediate container 251d6741c37e
---> 95c4aa62d74a
Step 64/78 : RUN cat /home/ip_variable
---> Running in 8825ef517fb8
172.17.0.2/16
Removing intermediate container 8825ef517fb8
---> 39672eb7021d
Step 65/78 : RUN cat /home/ip_change_script.sh
---> Running in 2161051ee4cf
#!/bin/sh -x
sed -i 's:PRIVATEIP:'172.17.0.2/16':g' /etc/fail2ban/jail.local
sed -i 's:PRIVATEIP:'172.17.0.2/16':g' /etc/opendkim/TrustedHosts
Removing intermediate container 2161051ee4cf
---> 407ccc7106f7
Step 66/78 : RUN chmod 755 /home/ip_change_script.sh
---> Running in 0f6ca7f78ba8
Removing intermediate container 0f6ca7f78ba8
---> 250afb327db0
Step 67/78 : RUN sh /home/ip_change_script.sh
---> Running in 4b209e18854b
Removing intermediate container 4b209e18854b
---> d45d024e1359
Step 68/78 : RUN touch /home/service_boot.log
---> Running in 3548dc45f466
Removing intermediate container 3548dc45f466
---> 587527e18ab2
Step 69/78 : RUN cat /home/service_boot.log
---> Running in b068b00cd584
Removing intermediate container b068b00cd584
---> 3183e6b281ed
Step 70/78 : COPY boot_service.sh /home/boot_service.sh
---> 9a73dd4fd87d
Step 71/78 : RUN chmod 755 /home/boot_service.sh
---> Running in 2f226574e28d
Removing intermediate container 2f226574e28d
---> 8a0c14218e1b
Step 72/78 : RUN cat /home/boot_service.sh
---> Running in 5fa64827b6dd
Присваивание не производит вывода, поэтому бессмысленно передавать его другому процессу.
Вместо этого используйте ;
, чтобы разделить конвейер на две последовательные команды:
IP=$(cat /root/ip_variable); sed -i "s/PRIVATEIP/$IP/g" /etc/fail2ban/jail.local
Я не знаком с Docker и его командой RUN
. Если требуется только одна команда , используйте
RUN sh -c 'IP=$(cat /root/ip_variable); sed -i "s/PRIVATEIP/$IP/g" /etc/fail2ban/jail.local'
или
RUN sed -i "s/PRIVATEIP/$(cat /root/ip_variable)/g" /etc/fail2ban/jail.local
Это работает для меня:
FROM alpine
COPY ipaddr /ipaddr
COPY ipconf /ipconf
RUN export IPADDR=$(cat /ipaddr) ; sed -i -r "s/IPADDR/${IPADDR}/g" /ipconf
CMD cat /ipconf
С ipconf и ipaddr
IP address is IPADDR
1.2.3.4
Тогда:
>docker build -t dynchange.
Sending build context to Docker daemon 5.12kB
Step 1/5 : FROM alpine
---> 3fd9065eaf02
Step 2/5 : COPY ipaddr /ipaddr
---> Using cache
---> 1828c3157d41
Step 3/5 : COPY ipconf /ipconf
---> 4f43e88e4425
Step 4/5 : RUN export IPADDR=$(cat /ipaddr) ; sed -i -r "s/IPADDR/${IPADDR}/g" /ipconf
---> Running in 722c3d3d9d9e
Removing intermediate container 722c3d3d9d9e
---> 32e31198b70a
Step 5/5 : CMD cat /ipconf
---> Running in 72ea59543a7f
Removing intermediate container 72ea59543a7f
---> 73f8a50d650a
Successfully built 73f8a50d650a
Successfully tagged dynchange:latest
>docker run --rm dynchange
IP address is 1.2.3.4
Однако именно так я бы не поступил. Лучше использовать аргумент сборки:
FROM alpine
COPY ipconf /ipconf
ARG IPADDR
RUN sed -i -r "s/IPADDR/${IPADDR}/g" /ipconf
CMD cat /ipconf
Тогда:
>docker build -t dynchange --build-arg IPADDR=4.5.6.7 .
Sending build context to Docker daemon 5.12kB
Step 1/5 : FROM alpine
---> 3fd9065eaf02
Step 2/5 : COPY ipconf /ipconf
---> Using cache
---> f5ac88ee48d5
Step 3/5 : ARG IPADDR
---> Running in 58d972e14660
Removing intermediate container 58d972e14660
---> fc3de48160c6
Step 4/5 : RUN sed -i -r "s/IPADDR/${IPADDR}/g" /ipconf
---> Running in 8ec855697510
Removing intermediate container 8ec855697510
---> 67e946559316
Step 5/5 : CMD cat /ipconf
---> Running in a5260c593c02
Removing intermediate container a5260c593c02
---> 567a31a517d1
Successfully built 567a31a517d1
Successfully tagged dynchange:latest
>docker run --rm dynchange
IP address is 4.5.6.7
Однако я даже не уверен, что это правильное решение. Я бы либо:
COPY
. Это дает полный контроль над его содержимым. CMD
или ENTRYPOINT
могут быть сценарием, который исправляет файл перед вызовом основной команды. Вы также можете передать файл конфигурации как VOLUME (. Это поможет избежать проблем, если CMD запускается от имени пользователя приложения, а для исправления конфигурации требуются привилегии root ).