shell脚本中的头列验证



"分隔文件应具有列标题以下的

Activity
Activity+ ID
Description
Status

上传后,在开始使用SQLLDR处理文件之前,我确保上传的文件有确切数量的头,头的名称匹配并且顺序相同。

代码:

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 "nn"
fi
done

数据:

Activity|Activity+ ID|Description|Status
Test|1234|First activity|Open

这总是打印缺少"活动+"列,尽管它存在于文件中。在我去除"+"从上传的头和文件来看,它正在按预期工作。我如何更改上面的代码以使用"+&";。我引用了bash的答案来识别和验证文件头,以构建这个解决方案

注意:对于OP想要做什么仍然有点困惑(例如,header被定义为整数,但后来被引用为数组("${header[@]}"))

假设:

  • 如果.csv文件第一行中以|分隔的字段数与fields[]数组中的条目数不匹配,则打印错误
  • .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[@]}相同的这种特殊情况,不产生输出。

其他测试用例:

标题[]中的第二个字段拼写不同

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个条目,但都与字段[]中的相应条目不同

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应该能够调整代码以提供所需的输出和/或设置一些变量用于后续条件操作(例如,如果触发了echo,则中止处理,如果触发echo,则禁用后续处理,等等)。