我有一个具有以下结构的文件:
ma${token}jid-azimi-865131021
javad-ya${token}rip-865132012
这是我的程序:
IFS="-"
token="12345678"
cat input.txt | while read col1 col2 col3; do
echo ${col1}
echo ${col2}
echo ${col3}
echo "********************************"
done
我想${token}
在读取文件时插入。因为 token 是一个动态单词,我不能每次都在文件中更改它。所以我添加${token}
到文件一次。但程序的输出是:
ma${token}jid
azimi
865131021
********************************
javad
ya${token}rip
865132012
********************************
为什么会发生这种情况?ma${token}jid
应该像这样展开:echo ma${token}jid
,然后12345678
应该插入。
答案1
回显时的变量不受变量扩展的影响。前置eval
到echo
.这可能适用于简单的情况,但如果您的字符串包含|
或引号,则可能会中断。或者,只需进行替换:
echo ${col1/'${token}'/$token}
答案2
的值为col1
13 个字符的字符串ma${token}jid
。当您echo ${col1}
不加引号写入时,shell 会替换${col1}
为变量的值,然后执行分词(即在$IFS
字符处将值分解为单独的单词)和文件名生成(即通配符)。变量值不会使用 shell 语法进行递归扩展。如果您在变量替换周围使用双引号(除非您有充分的理由不这样做,否则您应该这样做),则"$col1"
直接扩展为 的值col1
。
如果您的字符串足够温和(即,除了${token}
您想要替换的字符之外,不包含 shell 特殊字符),那么您可以根据$col1
您作为 shell 片段评估的字符串构造一个字符串。在您的示例中,将打印以下行ma12345678jid
:
eval "echo $col1"
或者,将标记替换${token}
为所需值。您可以通过 bash 中的字符串替换来完成此操作:
while read -r col1 col2 col3; do
echo "${col1//'${token}'/$token}"
echo "${col2}"
echo "${col3}"
echo "********************************"
done <input.txt
您还可以使用awk
, 作为预处理或后处理步骤(取决于您是否也想在其他列中执行替换)。
<input.txt awk -v repl="$token" '{gsub(/\${token}/, repl); print}' |
while read …
您可以使用 执行替换,但前提是您确定替换文本中sed
没有出现任何字符和换行符(如果您确定没有出现另一个字符,则可以将分隔符更改为其他字符)在)。&\/
$token
/
$token
<input.txt sed -e "s/\\\${token}/$token/" |
while read …