vários canais em loop, salvando pipeline-result a array

0

Estou tentando fazer o seguinte (usando o bash): Procure por arquivos que sempre tenham o mesmo nome e extraiam dados desses arquivos. Eu quero armazenar os dados extraídos em novas matrizes Eu estou quase lá, eu acho, veja o código abaixo.

Os arquivos que estou procurando por todos têm este formato:

 #!/bin/bash
  echo "the concentration of NDPH is 2 mM, which corresponds to 2 molecules in a box of size 12 nm (12 x 12 x 12 nm^3)" > README_test

#find all the README* files and save the paths into an array called files
  files=()
  data1=()
  data2=()
  data3=()

  while IFS=  read -r -d $'
echo ${data1[0]}
'; do files+=("$REPLY") #open all the files and extract data from them while read -r line do name="$line" echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /of/{f=1}' echo "$name" echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /of/{f=1}' data1+=( "$echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /of/{f=1}' )" ) # variables are not preserved... # data2+= echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /is/{f=1}' echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /size/{f=1}' # variables are not preserved... # data3+= echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /size/{f=1}' done < "$REPLY" done < <(find . -name "README*" -print0) echo ${data1[0]}

A questão é que o pipe me dando a saída exata que eu quero dos arquivos está "não funcionando" (as variáveis não são preservadas) nos loops. Eu não tenho idéia de como / se eu posso usar a substituição de processos para conseguir o que eu quero: um array (data1, data2, data3) preenchido com a saída dos pipes.

ATUALIZAÇÃO: Então, eu não estava atribuindo as coisas para o array corretamente (veja data1, que está apropriadamente atribuindo sth agora). Mas por que são

echo "$name" | tr ' ' '\n'|  awk 'f{print;f=0;exit} /of/{f=1}'

e

  #!/bin/bash
  echo "the concentration of NDPH is 2 mM, which corresponds to 2 molecules in a box of size 12 nm (12 x 12 x 12 nm^3)" > README_test
  files=()
  data1=()
  data2=()
  data3=()

  get_some_field() {    
 echo "$1" | tr ' ' '\n'|  awk -vkey="$2" 'f{print;f=0;exit} $0 ~ key {f=1}' 
  }

  #find all the README* files and save the paths into an array called files
  while IFS=  read -r -d $'
 #!/bin/bash
  echo "the concentration of NDPH is 2 mM, which corresponds to 2 molecules in a box of size 12 nm (12 x 12 x 12 nm^3)" > README_test

#find all the README* files and save the paths into an array called files
  files=()
  data1=()
  data2=()
  data3=()

  while IFS=  read -r -d $'
echo ${data1[0]}
'; do files+=("$REPLY") #open all the files and extract data from them while read -r line do name="$line" echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /of/{f=1}' echo "$name" echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /of/{f=1}' data1+=( "$echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /of/{f=1}' )" ) # variables are not preserved... # data2+= echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /is/{f=1}' echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /size/{f=1}' # variables are not preserved... # data3+= echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /size/{f=1}' done < "$REPLY" done < <(find . -name "README*" -print0) echo ${data1[0]}
'; do files+=("$REPLY") #open all the files and extract data from them while read -r line do name="$line" echo "$name" echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /of/{f=1}' data1+=( "$(get_some_field "$name" of)" ) data2+=( "$(get_some_field "$name" is)" ) data3+=( "$(get_some_field "$name" size)" ) done < "$REPLY" done < <(find . -name "README*" -print0) echo ${data1[0]} echo ${data2[0]} echo ${data3[0]}

não é o mesmo?

SOLUÇÃO (de acordo com a resposta aceita por ilkkachu):

echo "$name" | tr ' ' '\n'|  awk 'f{print;f=0;exit} /of/{f=1}'
    
por gugy 25.07.2018 / 11:56

1 resposta

2

Suponho que você queira a saída do echo ... | awk armazenado em uma variável e, em particular, anexada a um dos arrays.

Primeiro, para capturar a saída de um comando, use "$( cmd... )" (substituição de comando). Como um exemplo trivial, isso imprime seu nome de host:

var=$(uname -n)
echo $var

Em segundo lugar, para anexar a um array, você precisa usar a sintaxe de atribuição de matriz, com parênteses em torno do lado direito. Isso acrescentaria o valor de var à matriz:

array+=( $var )

Em terceiro lugar, a expansão de $var e a substituição de comandos $(...) estão sujeitas à divisão de palavras, portanto, você deseja usar parênteses em torno deles. Novamente, um exemplo trivial, isso coloca a saída completa de uname -a como um elemento único na matriz:

array+=( "$(uname -a)" )

Ou, no seu caso, na íntegra:

data1+=( "$(echo "$1" | tr ' ' '\n'|  awk 'f{print;f=0;exit} /of/{f=1}')" )

(Observe que as aspas dentro da substituição do comando são distintas das aspas fora dele. A citação antes de $1 não impede que as citações sejam iniciadas fora $() , diferentemente do que a sintaxe hilighting no SE parece implicar.)

Você pode simplificar a leitura colocando o pipeline em uma função:

get_data1() {
    echo "$name" | tr ' ' '\n'|  awk 'f{print;f=0;exit} /of/{f=1}'
}
...
data1+=( "$(get_data1)" )

Ou, como os pipelines parecem semelhantes, use a função para evitar a repetição do código:

get_some_field() {
    echo "$1" | tr ' ' '\n'|  awk -vkey="$2" 'f{print;f=0;exit} $0 ~ key {f=1}'
}

e depois

data1+=( "$(get_some_field "$name" of)" )
data2+=( "$(get_some_field "$name" is)" )
data3+=( "$(get_some_field "$name" size)" )

(Se eu leio seu pipeline corretamente, isto é, eu não testei o código acima.)

    
por 25.07.2018 / 12:45