Script de shell para localizar e substituir o valor do arquivo csv [closed]

1

Estou tentando gravar um script de shell para pesquisar um valor de célula em um arquivo csv e substituir uma célula correspondente na mesma linha.

Abaixo está meu arquivo csv ( report.csv )

#,Device,Status
1,Device1,Used
2,Device2,Free
3,Device3,Free

Isso é o que eu queria fazer:

O usuário digitará o nome do dispositivo como entrada durante a execução do script.

Por exemplo, Digite o nome do dispositivo:
 usuário entra "Device2"

Próxima etapa: o script deve pesquisar Device2 em report.csv . Se encontrar Dispositivo2 , verifique o valor na coluna status correspondente a ele e, se o valor for Gratuito , substitua-o por Usado , senão saia do script dizendo Device2 já em uso .

Eu tentei com o seguinte código

#!/bin/bash
dvc=""
FILE_HOME="/tmp/test/"

update_value () {  
  awk -F, -v d="$dvc" '$2==d{if($3=="Free")$3="Used"; else print d "In use"; input_value;}1' \
      OFS=, "$FILE_HOME"/report.csv > "$FILE_HOME"/report1.csv  
  mv "$FILE_HOME"/report1.csv "$FILE_HOME"/report.csv
}

input_value () {
  echo -e "Enter the device name:\n"
  read dvc
  update_value
}

input_value

Esse código é bom quando a instrução if é true .
Mas quando a declaração if é false , ela não está chamando a função input_value da seção else. Apenas imprime Device # In use junto com outras entradas no arquivo csv para o novo arquivo.

Eu fico abaixo dos arquivos de saída

  • quando a entrada é Device2 :

    #,Device,Status
    1,Device1,Used
    2,Device2,Used
    3,Device3,Free

  • quando a entrada é Device1 :

    #,Device,Status
    Device1 In use
    1,Device1,Used
    2,Device2,Free
    3,Device3,Free

Essa é a abordagem correta que estou fazendo?
Eu ficaria feliz em ver se existe uma abordagem diferente / melhor para alcançar o requisito.

    
por sajesh pp 02.08.2017 / 15:40

2 respostas

1

Escreva sua mensagem de erro para stderr .

awk -F, OFS=, -v d="$dvc" '
    $2==d {
      if($3=="Free") $3="Used"
      else print d "In use" > "/dev/stderr"
      print
    }' $FILE_HOME/report.csv > $FILE_HOME/report1.csv

Isso fará com que apareça na tela (se stderr não for redirecionado), e não na saída padrão.

Dito isso, há coisas que você pode fazer para tornar seu script mais simples de se trabalhar. Que tal isso:

#!/usr/bin/awk -f
BEGIN {
  FS=","
  OFS=","
  FILE_NAME="/tmp/test/report1.csv"
  print "Enter the device name:"
  getline d < "-"
}

$2==d && $3=="Free" {
  $3="Used"
  print > FILE_NAME
  next
}

$2==d {
  print d " in use" > "/dev/stderr"
}

{
  print > FILE_NAME
}

Invoque-o com

$ script_name /tmp/test/report.csv

e / ou envolva-o em bash como quiser.

    
por 02.08.2017 / 15:55
1

Você está limitado apenas ao shell e ao awk? Você consegue usar o SQLite para armazenar seus dados ou pelo menos para analisá-los?

sqlite> .mode csv
sqlite> .import report.csv report
sqlite> update report set status="Used" where Device="Device2";
sqlite> select * from report;
 1,Device1,Used
 2,Device2,Used
 3,Device3,Free

Ou você pode usar linguagens de programação mais gerais, como o Python, para a sua tarefa?

import csv

with open('report.csv') as csvfile:
  reader = csv.DictReader(csvfile)
  for row in reader:
    if row['Device'] == "Device3":
      row['Status'] = "Used"
    print row

{'Device': 'Device1', 'Status': 'Used', '#': '1'}
{'Device': 'Device2', 'Status': 'Free', '#': '2'}
{'Device': 'Device3', 'Status': 'Used', '#': '3'}
    
por 03.08.2017 / 08:54