Я пытаюсь передать плоскую базу данных с некоторыми именами через скрипт, чтобы игнорировать определенные поля и проверять другие. В настоящее время это то, что я получил.

Что бы я использовал в своем тогдашнем заявлении, чтобы игнорировать комментарии и пробелы?

РЕДАКТИРОВАТЬ: Образец читаемого файла

Bob,Brown,Smith,39
#Alex,Jay,Jones,83

Justin,Michael,White,18
 James,Paul,Weis,54

РЕДАКТИРОВАТЬ: Затем я разделяю каждое имя

IFS_SAVE=${IFS}
IFS=,

while read value1 value2 value3 value4
do
 echo "First name ${value1}"
 echo "Middle name ${value2}"
 echo "Last name ${value3}"
 echo "Age ${value4}"
done < ${1}

Затем я пытаюсь игнорировать пустые строки в файле

while read value1 value2 value3 value4
do
if [ -z ${value1} ]
 then
   echo "blank line exists"
 fi
done < ${1}

Затем я пытаюсь игнорировать закомментированные строки в файле

while read value1 value2 value3 value4
do
if [ "${value1:0:1}" = "#" ]
 then
    echo "comment exists"
 fi
done < ${1}

Отсюда я не смог заставить это работать

Я пытаюсь проверить, начинаются ли поля с пробела или заканчиваются им.

while read value1 value2 value3 value4
do
if [[ ${value1} = *[[:space:]]* ]]
then
    echo "space exist"
fi
done < ${1}

РЕДАКТИРОВАТЬ: идеальный результат

First name Bob
Middle name Brown
Last name Smith
Age 39
First name Justin
Middle name Michael
Last name White
Age 39
 James,Paul,Wise,54 space exist
3
dylanw 14 Окт 2020 в 07:57
1
Можете ли вы предоставить нам комментарий, пробел, а также пример ввода пробела, чтобы мы могли попробовать его самостоятельно? мы можем заскриптовать его сейчас, но это может быть непреднамеренным решением, если нет образца ввода
 – 
hanysfa
14 Окт 2020 в 06:55
Я прикрепил образец того, как выглядит файл. Благодарность
 – 
dylanw
14 Окт 2020 в 07:26

2 ответа

Используйте инструмент обработки текста для обработки текста, а не сотни вызовов неподходящих инструментов, таких как read или echo в цикле.

Здесь очевидным способом обработки табличных данных является awk:

awk -F, -v OFS='\n' '
  ! /^[#[:space:]]/ {
    print "First name "  $1, \
          "Middle name " $2, \
          "Last name "   $3, \
          "Age "         $4
  }' < you-file

Условие ! /^[#[:space:]]/ соответствует строкам, которые не начинаются (!) (^) с символа # или пробела. Вы также можете использовать /^[^#[:space:]]/ для сопоставления строк, которые начинаются с символа, отличного от # или пробела, что фактически также пропускает пустые строки или добавляет && NF == 4 к пропустите строки, в которых нет ровно 4 полей.

Или передать строки с начальными или конечными пробелами нетронутыми, как в ожидаемом результате:

awk -F, -v OFS='\n' '
  /^[[:space:]]/ || /[[:space:]]$/ {print; next}

  /^[^#]/ && NF == 4 {
    print "First name "  $1, \
          "Middle name " $2, \
          "Last name "   $3, \
          "Age "         $4
  }' < you-file

(Здесь мы предполагаем POSIX-совместимый awk; с mawk замените [:space:] на жестко закодированный список пробельных символов, который вы ожидаете найти в начале, поскольку mawk не не поддерживает классы символов POSIX).

Также имейте в виду, что символ возврата каретки (также известный как CR / \r / ^M) считается символом [:space:]. Если бы входной файл был текстовым файлом из ОС Microsoft, где разделителем строк является CRLF, а не просто LF в Unix, то каждая строка заканчивалась бы символом пробел. Сначала вы захотите запустить файл через dos2unix, чтобы преобразовать его в формат Unix.

8
Stéphane Chazelas 14 Окт 2020 в 08:30

Поскольку разделение слов происходит через IFS, а IFS по умолчанию состоит из «табуляции/пробела/новой строки», и вам нужно установить IFS в запятую ,, поэтому вам потребуется:

while IFS=, read -r  …

А также измените ${value1} = *[[:space:]]* на "${value1}" =~ ^[[:space:]] на сопоставление с образцом, которое начинается с пробела; и нет реального слова, означающего, что это просто то, как разбивается IFS (здесь это одна запятая).

См. также Почему использование цикла оболочки для обработки текста считается плохой практикой?

2
αғsнιη 14 Окт 2020 в 07:37
Извините, я отредактировал свой пост, чтобы лучше отразить то, что я пытался сделать. В настоящее время я использую IFS для разделения имен,
 – 
dylanw
14 Окт 2020 в 07:37
Что IFS - это оболочка-IFS, которую вы установили, здесь IFS для read IFS
 – 
αғsнιη
14 Окт 2020 в 07:39
Так while IFS=, read value1 value2 value3 value4 do if [ -z ${value1} ] then echo "blank line exists" fi done < ${1} это то, что вы говорите?
 – 
dylanw
14 Окт 2020 в 07:41