Как изменить значения строковых значений на индексное значение для использования в массиве?

Мы можем объединить все команды из исходного columns = конвейера оболочки в один sed скрипт. Этот сценарий sed изменяет только первую строку ввода и затем завершает работу. Следующее делает в точности то же самое, что и columns = в исходном вопросе:

columns=$(
    sed '               
        1 {                                   # execute block on line 1
            s/-/_/g     
            s/ /_/g     
            s/COL[0-9]\+_BDID/DROP_BDID/g
            s/COL[0-9]\+_//g
            s/\t/\n/g   
            y/abcdefghijklmnopqrstuv/ABCDEFGHIJKLMNOPQRSTUV/
            q                                 # quit after line 1
        }
    ' "$1"
)

# . . .

Я предпочитаю многострочный формат также для удобства чтения. Несмотря на то, что исходное заявление было в одной строке, оно было гораздо менее эффективным и, на мой взгляд, более трудным для чтения.yomd

Теперь у вас есть заголовки из входного файла (аргумент 1), хранящиеся в переменной columns , разделенных символами новой строки. Вы можете перебирать строки в $ columns с помощью цикла for , это разделит имена столбцов в cut_cols символами новой строки:

cut_cols="$(
    for col in $columns
    do
        case $col in
        (*__LINE_NUMBER*|*CONFIDENCE*|*DROP_BDID*|*LINE_NUMBER*|*ZIP9*|*ZIP9MATCH*)
                echo "$col"
                ;;
        esac
    done
)"

В зависимости от вашего предпочтений, это делает то же самое:

cut_cols=
for col in $columns
do
    case $col in
        (*__LINE_NUMBER*|*CONFIDENCE*|*DROP_BDID*|*LINE_NUMBER*|*ZIP9*|*ZIP9MATCH*)
            cut_cols="$cut_cols $col"
            ;;
    esac
done
cut_cols=$(echo "$cut_cols" | sed 's/^ *//; s/ /\n/g')

Я не тестировал ваш цикл массива для cut_cols , потому что я не использую массивы оболочки. Вышеупомянутый метод перебора $ columns является более универсальным и традиционным методом. Массивы являются расширением, доступным не во всех оболочках.

После того, как вы назначили cut_cols , вы можете перебирать его так же, как $ columns .

Чтобы отправить новый заголовок с данными исходного файла, распечатайте новый заголовок, а затем распечатайте все, кроме первой строки исходного файла. Сделайте это в группе команд (между { и } ), чтобы вы могли перенаправить вывод обеих команд вместе, как если бы они были одной программой.

Следующий код создает полный исходный текстовый файл без исходной строки заголовка и с той, которую вы создали, и отправляет его на stdin из vsql :

# . . .

{                                   # start command group

    echo "$columns" | tr '\n' '\t'; # print with tabs instead of newlines
    echo                            # add newline record separator
    sed 1d "$1"                     # print all but 1st line of "$1"

} |                                 # pipe as one file to vsql

/opt/vertica/bin/vsql -U ${4} -w ${5} -h ${database} \
    -c "copy $schema.$table from STDIN delimiter E'\t' direct no escape;"
0
01.12.2018, 09:38
2 ответа

Не используйте циклы оболочки для обработки текста , используйте утилиту обработки текста.

awk -F, '{for (i = 0; i < NF; i++) printf "v[%d] = %s\n", i, $(i+1)}' < file1.txt

Если у вас есть для использования цикла bash, то было бы разумнее записать его как:

while IFS=, read -ra v; do
  for i in "${!v[@]}"; do
    printf 'v[%d] = %s\n' "$i" "${v[i]}"
  done
done < file1.txt

С оговоркой, что если последнее поле пусто, оно будет пропущено .

1
28.01.2020, 02:41

Есть несколько проблем с вашим скриптом.

  • Имя переменной в V=($DEL_REMOVE)должно бытьV=($DELIM_REMOVE)
  • Вы устанавливаете IFS на запятую (,), но удаляете запятую с помощью sed.

Сделав эти два изменения, ваш скрипт начинает делать что-то разумное.

Внося некоторые другие изменения, ваш скрипт становится:

#!/bin/bash

IFS=' '                           # Use the space to split
set -f                            # Avoid globing of values with *,? or []
while read -r line                # read the variable without removing backslash
do
    v=( ${line//,/ } )            # Convert to an array by splitting with the shell.
    for i in "${!v[@]}"; do
            printf 'v[%s] = %s\n' "$i" "${v[i]}"
        done
done < file1.txt

Который будет печатать:

v[0] = 101
v[1] = Harish
v[2] = BAN
v[0] = 102
v[1] = Srinu
v[2] = HYD

Вы этого и ожидали?

0
28.01.2020, 02:41

Теги

Похожие вопросы