2017-09-22 60 views
0

這些完全相同,但第一個不起作用,第二個起作用。任何人都知道如何獲得第一個工作?我認爲這是空的問題。我嘗試在第一個替換空值,但仍然無法讓它工作。也許我錯誤地替換了空值?用新行代替空值 - 我認爲

1)這並不工作

#!/bin/bash 

export CSM_DATA_DIR="/opt/halogen/dbservice/changes/Ayman/test2" 
export CUSTOMER_LIST_FILES="${CSM_DATA_DIR}/*_customer_list.csv" 
export ELMS_STORAGE_FILES="${CSM_DATA_DIR}/*_elms_storage.csv" 


paste <(tr ' ' '\n' <<<"$CUSTOMER_LIST_FILES") <(tr ' ' '\n' <<<"$ELMS_STORAGE_FILES") | while read first_name last_name 
do 
echo $first_name : $last_name 
done 

輸出錯了,應該是兩條線,並應正確劃分

/opt/halogen/dbservice/changes/Ayman/test2/sl1_customer_list.csv /opt/halogen/dbservice/changes/Ayman/test2/sl2_customer_list.csv : /opt/halogen/dbservice/changes/Ayman/test2/sl1_elms_storage.csv /opt/halogen/dbservice/changes/Ayman/test2/sl2_elms_storage.csv 

2)本工程爲intneded

#!/bin/bash 
export fname="/opt/halogen/dbservice/changes/Ayman/test2/sl1_customer_list.csv /opt/halogen/dbservice/changes/Ayman/test2/sl2_customer_list.csv" 
export lname="/opt/halogen/dbservice/changes/Ayman/test2/sl1_elms_storage.csv /opt/halogen/dbservice/changes/Ayman/test2/sl2_elms_storage.csv" 

paste <(tr ' ' '\n' <<<"$fname") <(tr ' ' '\n' <<<"$lname") | while read first_name last_name 
do 
echo $first_name : $last_name 
done 

輸出正確,兩行並行讀取變量

/opt/halogen/dbservice/changes/Ayman/test2/sl1_customer_list.csv : /opt/halogen/dbservice/changes/Ayman/test2/sl1_elms_storage.csv 
/opt/halogen/dbservice/changes/Ayman/test2/sl2_customer_list.csv : /opt/halogen/dbservice/changes/Ayman/test2/sl2_elms_storage.csv 

我已經發布了緊靠一個星期的問題現在得到所有的答案,我不知道該說些什麼,但謝謝你,我會希望回到這一回社區1天

+0

故意引用第一個示例中的星號嗎? – user000001

+0

@ user000001,即使它不是,因爲結果被存儲到一個字符串而不是一個列表,它是用來存儲多個文件名的錯誤數據結構。 –

+0

順便說一句 - 'export'只在你想通過把子進程放到環境中而不是將它保存在本地shell的內存中的時候才能使用一個變量的情況下才需要。並參見http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html re:POSIX定義的命名約定(全大寫名稱用於對shell和操作系統有意義的變量,而小寫的名字是保留的供應用使用)。 –

回答

2

原代碼實際上有一些微妙的錯誤。在你的字符串中沒有NUL要替換,因爲C字符串(如bash所使用的)不能包含文字NUL:它們由第一個NUL存在終止。

因此,將文件名列表存儲在bash(或C)中的單個字符串中是不安全的,因爲文件名可以包含空格,換行符 - 除NUL以外的任何字符。因此,沒有辦法知道某個名字何時結束,下一個名字何時開始。

爲了安全地遍歷文件對(這似乎是你正在做的),將每個glob展開成一個數組,並且同時遍歷這兩個數組。

#!/usr/bin/env bash 
#    ^^^^- not /bin/sh, which doesn't support arrays 

csm_data_dir="/opt/halogen/dbservice/changes/Ayman/test2" 
customer_list_files=("${csm_data_dir}"/*_customer_list.csv) 
elms_storage_files=("${csm_data_dir}"/*_elms_storage.csv) 

for idx in "${!customer_list_files[@]}"; do 
    customer_list_file=${customer_list_files[$idx]} 
    elms_storage_file=${elms_storage_files[$idx]} 
    printf '%q : %q\n' "$customer_list_file" "$elms_storage_file" 
done 

注意,*秒 - 水珠人物 - 中沒有報價。這會導致它們在定義數組變量時展開。

+0

謝謝,這工作,但爲什麼我的代碼不能在第二個例子中工作?忽略「微妙」的錯誤 – aymanzone

+0

「第二」是什麼意思?在第一個(標記爲「這不起作用」)中,這是因爲globs沒有在引用字符串中擴展,所以直到使用'echo'的行纔會發生替換。如果你使用'echo'$ {first_name}:$ {last_name}'',用引號,這會更明顯一些(因爲這會阻止glob在'echo'調用期間被擴展)。 –

+0

也就是說,'CUSTOMER_LIST_FILES =「$ {CSM_DATA_DIR}/* _ customer_list.csv」'實際上並不是用文件列表替換'*',''<$「$ CUSTOMER_LIST_FILES」;只有當您運行'echo $ CUSTOMER_LIST_FILES'(不帶引號)時,纔會使用原始代碼進行擴展。 –