Мы можем объединить все команды из исходного 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;"
Не используйте циклы оболочки для обработки текста , используйте утилиту обработки текста.
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
С оговоркой, что если последнее поле пусто, оно будет пропущено .
Есть несколько проблем с вашим скриптом.
V=($DEL_REMOVE)
должно бытьV=($DELIM_REMOVE)
,
), но удаляете запятую с помощью 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
Вы этого и ожидали?