header 脚本中的 shell 列验证
header columns validation in shell script
"|"分隔文件应在 headers
列下方
Activity
Activity+ ID
Description
Status
上传后,在使用 SQLLDR 开始处理文件之前,我确保上传的文件有准确的 header 个数,header 个名称匹配且顺序相同。
代码:
declare -i header=4
fields=(
"Activity"
"Activity+ ID"
"Description"
"Status"
)
for i in "Test File.csv"; do
read -r line < "$i"
oldIFS="$IFS"
IFS=$'|'
fldarray=( $line );
IFS="$oldIFS"
nfields=${#fldarray[@]}
if (( nfields < header ))
then
printf "error: only '%d' fields in file '%s'\nmissing:" "$nfields" "$i"
else
for item1 in "${header[@]}"; do
for item2 in "${fields[@]}"; do
if [[ $item1 != $item2 ]]; then
Array3+=("$item1")
fi
done
done
echo "not matching" ${Array3[@]}
printf "\n\n"
fi
done
数据:
Activity|Activity+ ID|Description|Status
Test|1234|First activity|Open
这总是打印缺少 Activity+ 列,尽管它存在于文件中。在我从 header 中删除“+”并上传文件后,它按预期工作。
如何更改上面的代码以使用“+”验证列 headers。
我参考了 的答案来构建这个解决方案
注意: 对于 OP 想要做什么仍然有点困惑(例如,header
被定义为整数但后来被引用为数组("${header[@]}"
))
假设:
- 如果
.csv
文件第一行中的 |
分隔字段的数量与 fields[]
数组中的条目数量不匹配
- header
.csv
文件中的字段必须与 fields[]
数组 中的条目完全匹配(拼写和顺序)
- 打印
fields[]
数组中与 .csv
文件第一行的 |
分隔字段不完全匹配的条目
我们将保留当前的 fields[]
数组:
fields=("Activity" "Activity+ ID" "Description" "Status")
将.csv
文件的第一行拉入headers[]
数组:
IFS='|' read -r -a headers < test.csv # read first line from test.csv, break on '|' delimiter, store in headers[] array
给我们:
$ typeset -p fields headers
declare -a fields=([0]="Activity" [1]="Activity+ ID" [2]="Description" [3]="Status")
declare -a headers=([0]="Activity" [1]="Activity+ ID" [2]="Description" [3]="Status")
现在对OP的if/else/for/fi
代码做一些修改:
if [[ "${#fields[@]}" -ne "${#headers[@]}" ]] # field count mismatch?
then
echo "error: field count mismatch: expecting ${#fields[@]} / found ${#headers[@]}"
else
Array3=() # init array Array3[]
for ((i=0;i<${#fields[@]};i++)) # loop through indices of fields[] array
do
[[ "${fields[$i]}" != "${headers[$i]}" ]] && \ # if same position in both arrays is not a match then ...
Array3+=("${fields[$i]}") # add fields[] entry to Array3[]
done
[[ "${#Array3[@]}" -ne 0 ]] && \ # if Array3[] not empty then ...
echo "not matching:" ${Array3[@]} # print list of fields to stdout
fi
对于这种特殊情况,${fields[@]}
和 ${headers[@]}
相同,不会生成任何输出。
其他测试用例:
headers[] 中的第二个字段拼写不同
declare -a fields=([0]="Activity" [1]="Activity+ ID" [2]="Description" [3]="Status")
declare -a headers=([0]="Activity" [1]="Activity+" [2]="Description" [3]="Status")
# the code generates:
not matching: Activity+ ID
headers[] 有 3 个条目
declare -a fields=([0]="Activity" [1]="Activity+ ID" [2]="Description" [3]="Status")
declare -a headers=([0]="Activity" [1]="Activity+ ID" [2]="Status")
# the code generates:
error: field count mismatch: expecting 4 / found 3
headers[] 有 4 个条目,但都与 fields[]
中的相应条目不同
declare -a fields=([0]="Activity" [1]="Activity+ ID" [2]="Description" [3]="Status")
declare -a headers=([0]="Activity+ ID" [1]="Description" [2]="Status" [3]="Activity")
# the code generates:
not matching: Activity Activity+ ID Description Status
从这里 OP 应该能够调整代码以提供所需的输出 and/or 设置一些变量以用于 follow-on 条件操作(例如,如果 echo
被触发,禁用 follow-on 处理,如果 echo
被触发,等等)。
"|"分隔文件应在 headers
列下方Activity
Activity+ ID
Description
Status
上传后,在使用 SQLLDR 开始处理文件之前,我确保上传的文件有准确的 header 个数,header 个名称匹配且顺序相同。
代码:
declare -i header=4
fields=(
"Activity"
"Activity+ ID"
"Description"
"Status"
)
for i in "Test File.csv"; do
read -r line < "$i"
oldIFS="$IFS"
IFS=$'|'
fldarray=( $line );
IFS="$oldIFS"
nfields=${#fldarray[@]}
if (( nfields < header ))
then
printf "error: only '%d' fields in file '%s'\nmissing:" "$nfields" "$i"
else
for item1 in "${header[@]}"; do
for item2 in "${fields[@]}"; do
if [[ $item1 != $item2 ]]; then
Array3+=("$item1")
fi
done
done
echo "not matching" ${Array3[@]}
printf "\n\n"
fi
done
数据:
Activity|Activity+ ID|Description|Status
Test|1234|First activity|Open
这总是打印缺少 Activity+ 列,尽管它存在于文件中。在我从 header 中删除“+”并上传文件后,它按预期工作。
如何更改上面的代码以使用“+”验证列 headers。
我参考了
注意: 对于 OP 想要做什么仍然有点困惑(例如,header
被定义为整数但后来被引用为数组("${header[@]}"
))
假设:
- 如果
.csv
文件第一行中的|
分隔字段的数量与fields[]
数组中的条目数量不匹配 - header
.csv
文件中的字段必须与fields[]
数组 中的条目完全匹配(拼写和顺序)
- 打印
fields[]
数组中与.csv
文件第一行的|
分隔字段不完全匹配的条目
我们将保留当前的 fields[]
数组:
fields=("Activity" "Activity+ ID" "Description" "Status")
将.csv
文件的第一行拉入headers[]
数组:
IFS='|' read -r -a headers < test.csv # read first line from test.csv, break on '|' delimiter, store in headers[] array
给我们:
$ typeset -p fields headers
declare -a fields=([0]="Activity" [1]="Activity+ ID" [2]="Description" [3]="Status")
declare -a headers=([0]="Activity" [1]="Activity+ ID" [2]="Description" [3]="Status")
现在对OP的if/else/for/fi
代码做一些修改:
if [[ "${#fields[@]}" -ne "${#headers[@]}" ]] # field count mismatch?
then
echo "error: field count mismatch: expecting ${#fields[@]} / found ${#headers[@]}"
else
Array3=() # init array Array3[]
for ((i=0;i<${#fields[@]};i++)) # loop through indices of fields[] array
do
[[ "${fields[$i]}" != "${headers[$i]}" ]] && \ # if same position in both arrays is not a match then ...
Array3+=("${fields[$i]}") # add fields[] entry to Array3[]
done
[[ "${#Array3[@]}" -ne 0 ]] && \ # if Array3[] not empty then ...
echo "not matching:" ${Array3[@]} # print list of fields to stdout
fi
对于这种特殊情况,${fields[@]}
和 ${headers[@]}
相同,不会生成任何输出。
其他测试用例:
headers[] 中的第二个字段拼写不同
declare -a fields=([0]="Activity" [1]="Activity+ ID" [2]="Description" [3]="Status")
declare -a headers=([0]="Activity" [1]="Activity+" [2]="Description" [3]="Status")
# the code generates:
not matching: Activity+ ID
headers[] 有 3 个条目
declare -a fields=([0]="Activity" [1]="Activity+ ID" [2]="Description" [3]="Status")
declare -a headers=([0]="Activity" [1]="Activity+ ID" [2]="Status")
# the code generates:
error: field count mismatch: expecting 4 / found 3
headers[] 有 4 个条目,但都与 fields[]
中的相应条目不同declare -a fields=([0]="Activity" [1]="Activity+ ID" [2]="Description" [3]="Status")
declare -a headers=([0]="Activity+ ID" [1]="Description" [2]="Status" [3]="Activity")
# the code generates:
not matching: Activity Activity+ ID Description Status
从这里 OP 应该能够调整代码以提供所需的输出 and/or 设置一些变量以用于 follow-on 条件操作(例如,如果 echo
被触发,禁用 follow-on 处理,如果 echo
被触发,等等)。