Предположим, что вход input.json
Вот упрощенный метод с использованием Boost Spirit Qi:
#include
#include
#include
#include
#include
Печатает
std::istream& {anonymous}::operator>>(std::istream&, {anonymous}::Array&)
Parsed 13 elements:
--------------------
{ "A": 1, "B": 10, }
--------------------
{ "C": 3, "D": 12, }
--------------------
{ "E": 5, "F": 14, }
--------------------
{ "G": 7, "H": 16, }
--------------------
{ "I": 9, "J": 18, }
--------------------
{ "K": 11, "L": 20, }
--------------------
{ "M": 13, "N": 22, }
--------------------
{ "O": 15, "P": 24, }
--------------------
{ "Q": 17, "R": 26, }
--------------------
{ "S": 19, "T": 28, }
--------------------
{ "U": 21, "V": 30, }
--------------------
{ "W": 23, "X": 32, }
--------------------
{ "Y": 25, "Z": 34, }
То же дело:
namespace {
using Element = std::map;
struct Array : std::vector { };
namespace parser {
using namespace boost::spirit::x3;
rule s;
rule r;
rule e;
auto s_def = '"' >> ~char_('"') >> '"';
auto r_def = (s >> ':' >> int_) % ',';
auto e_def = '{' >> r >> '}';
BOOST_SPIRIT_DEFINE(s,r,e)
}
std::istream& operator>>(std::istream& is, Array& into) {
using namespace parser;
boost::spirit::istream_iterator f(is), l;
if (!phrase_parse(f, l, '{'
>> lit("\"values\"") >> ':' >> '[' >> (e % ',') >> ']'
>> '}', space, into))
{
is.setstate(is.rdstate() | std::ios::failbit);
}
return is;
}
}
Тот же выход с тем же main()
Это несколько отличается , Я решил не реализовывать operator>>
, потому что Boost Property на самом деле этого не дает.
#include
#include
#include
#include
Конечно, вывод снова, тот же, что и раньше.
Поскольку вы подключаетесь к циклу while, для запуска цикла while создается вспомогательная оболочка. Теперь этот дочерний процесс имеет свою собственную копию среды и не может передавать какие-либо переменные обратно в родительский (как в любом процессе unix).
Поэтому вам нужно будет провести реструктуризацию, чтобы вы не трубопроводы в петлю. В качестве альтернативы вы могли бы запустить функцию, например, и повторить значение, которое вы хотите вернуть из подпроцесса.
Я обошел это, когда я делал свой собственный маленький дю:
ls -l | sed '/total/d ; s/ */\t/g' | cut -f 5 |
( SUM=0; while read SIZE; do SUM=$(($SUM+$SIZE)); done; echo "$(($SUM/1024/1024/1024))GB" )
. Дело в том, что я создаю подоболочку с (), содержащую мою переменную SUM и while, но я подключаюсь к целое (), а не в то самое время, которое позволяет избежать получения.
Другой вариант - вывести результаты в файл из подоболочки и затем прочитать его в родительской оболочке. что-то вроде
#!/bin/bash
EXPORTFILE=/tmp/exportfile${RANDOM}
cat /tmp/randomFile | while read line
do
LINE="$LINE $line"
echo $LINE > $EXPORTFILE
done
LINE=$(cat $EXPORTFILE)
#!/bin/bash
OUTPUT="name1 ip ip status"
+export XCODE=0;
if [ -z "$OUTPUT" ]
----
echo "CRIT: $NAME - $STATUS"
- echo $((++XCODE))
+ export XCODE=$(( $XCODE + 1 ))
else
echo $XCODE
посмотреть, помогают ли эти изменения
Проблема в том, что процессы, связанные с трубой, выполняются в подоболочках (и, следовательно, имеют собственную среду). Все, что происходит внутри while
, не влияет на что-либо вне трубы.
Ваш конкретный пример можно решить, переписав канал на
while ... do ... done <<< "$OUTPUT"
или, возможно,
while ... do ... done < <(echo "$OUTPUT")
<( command )
, и это сэкономило мне много времени и головных болей. большой +1 к вам сэр :)
– Carlos Campderrós
30 January 2013 в 14:29
Еще одна опция:
#!/bin/bash
cat /some/file | while read line
do
var="abc"
echo $var | xsel -i -p # redirect stdin to the X primary selection
done
var=$(xsel -o -p) # redirect back to stdout
echo $var
EDIT: Здесь требуется xsel (установите его). Кроме того, вы можете использовать xclip: xclip -i -selection clipboard
вместо xsel -i -p
Это должно работать также (потому что эхо и while находятся в одной подоболочке):
#!/bin/bash
cat /tmp/randomFile | (while read line
do
LINE="$LINE $line"
done && echo $LINE )