Последний элемент в массиве не отображается внутри цикла - PullRequest
1 голос
/ 15 апреля 2019

Последний элемент массива не печатается должным образом из цикла

При изучении текстовых фильтров оболочки я создал небольшой скрипт awk, который форматирует вывод файла CSV, предоставляя встроенный заголовок.

Сценарий оболочки-оболочки вызывается из командной строки, и все, что он на самом деле делает, - это оборачивает скрипт awk и передает аргумент как переменную regex, которая является строкой поиска.

Сценарий сохраняет поля первой записи (NR==1) в массиве heading.Как только запись, содержащая строку поиска regex, найдена в теле CSV-файла, сценарий объединяет заголовок с соответствующим значением.

csv.sh:

#!/bin/bash

awk -f ~/Scripts/csv.awk -v "regex=$1" $2

csv.awk:

BEGIN {FS=",";}
NR==1 { 
  for (i=1; i<=NF; i++) { 
    heading[i]=$i; 
  } 
}
NR>1 {
  if ($0 ~ regex) {
    for (i=1; i<=length(heading); i++) {
      if(length($i) > 0) { 
        print(heading[i] ": " $i)
      } 
    }
    print("")
  }
}

Демонстрация

ship.csv:

name,country,displacement,length,beam,commissioned
Yamato,Japan,65027,256,38.9,16 December 1941
USS Enterprise,United States of America,19800,251.4,33.4,12 May 1938
Bismarck,Germany,41700,251,36,24 August 1940
HMS Dreadnought,United Kingdom,18120,160.6,25,2 December 1906
USS Iowa,United States of America,46000,270.43,32.97,22 February 1943
HMS Vanguard,United Kingdom,45200,248.2,32.9,12 May 1946

Вызов

$ csv Enterprise ships.csv

Ожидаемый результат

name: USS Enterprise
country: United States of America
displacement: 19800
length: 251.4
beam: 33.4
commissioned: 12 May 1938

Вывод терминала:

name: USS Enterprise
country: United States of America
displacement: 19800
length: 251.4
beam: 33.4
: 12 May 1938

На моем компьютере с Linux (Manjaro) вывод очень похож.Но на самом деле, если я перенаправлю вывод на pbcopy на моем Mac, заголовок появится после вставки:

name: USS Enterprise
country: United States of America
displacement: 19800
length: 251.4
beam: 33.4
commissioned
: 12 May 1938

Ответы [ 2 ]

1 голос
/ 15 апреля 2019

На основании комментария Гленна, не могли бы вы попробовать следующее.

awk 'BEGIN {FS=",";}
{gsub(/\r/,"")}
NR==1 { 
  for (i=1; i<=NF; i++) { 
    heading[i]=$i; 
  } 
}
NR>1 {
  if ($0 ~ regex) {
    for (i=1; i<=length(heading); i++) {
      if(length($i) > 0) { 
        print(heading[i] ": " $i)
      } 
    }
    print("")
  }
}'  Input_file
0 голосов
/ 15 апреля 2019

Передача массива в length функция менее переносимая .

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

NR==1 { 
  headercount=NF; # store the count
  for (i=1; i<=NF; i++) { 
    heading[i]=$i; 
  } 
}
NR>1 {
  if ($0 ~ regex) {
    for (i=1; i<=headercount; i++) { #Use the count
      if(length($i) > 0) {
        print(heading[i] ": " $i)
      }
    }
    print("")
  }
}

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

#!/bin/bash
dos2unix -q "$2" # This makes sure that the input file has unix style file endings
awk -f ./csv.awk -v "regex=$1" $2

Тест

$ ./csv.sh HMS ships.csv 
name: HMS Dreadnought
country: United Kingdom
displacement: 18120
length: 160.6
beam: 25
commissioned: 2 December 1906

name: HMS Vanguard
country: United Kingdom
displacement: 45200
length: 248.2
beam: 32.9
commissioned: 12 May 1946

Если ваши заголовки подделаны так, что у них нет, скажем, введенного в эксплуатацию столбца, это будет беспрепятственно работать и в этом сценарии.

Тест

$ ./csv.sh HMS ships.csv 
name: HMS Dreadnought
country: United Kingdom
displacement: 18120
length: 160.6
beam: 25

name: HMS Vanguard
country: United Kingdom
displacement: 45200
length: 248.2
beam: 32.9
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...