Awk 在文本文件中查找一个单词,并将其替换为文件名

Awk 在文本文件中查找一个单词,并将其替换为文件名,awk,Awk,我有很多文本文件,我想在其中找到单词“CASE”,并用相关的文件名替换它。 我试过了 但是我犯了以下错误 awk:源代码第1行上下文的语法错误为>>{gsub(/CASE/,print>{gsub(/CASE/,${为什么awk?sed是您想要的: while read -r file; do sed -i "s/CASE/${file##*/}/g" "$file" done < <( find . -type f ) find . -type f | while IF

我有很多文本文件,我想在其中找到单词“CASE”,并用相关的文件名替换它。 我试过了

但是我犯了以下错误


awk:源代码第1行上下文的语法错误为>>{gsub(/CASE/,print>{gsub(/CASE/,${为什么
awk
sed
是您想要的:

while read -r file; do 
    sed -i "s/CASE/${file##*/}/g" "$file"
done < <( find . -type f )
find . -type f |
while IFS= read -r file
do
    awk '{gsub(/CASE/,FILENAME)} 1' "$file" > "${file}.$$" &&
    mv "${file}.$$" "$file"
done
读取-r文件时;执行以下操作
sed-i“s/CASE/${file##*/}/g”“$file”

完成<为什么
awk
sed
是您想要的:

while read -r file; do 
    sed -i "s/CASE/${file##*/}/g" "$file"
done < <( find . -type f )
find . -type f |
while IFS= read -r file
do
    awk '{gsub(/CASE/,FILENAME)} 1' "$file" > "${file}.$$" &&
    mv "${file}.$$" "$file"
done
读取-r文件时;执行以下操作
sed-i“s/CASE/${file##*/}/g”“$file”

完成<您没有发布任何示例输入和预期输出,因此这是一个猜测,但可能这就是您想要的:

while read -r file; do 
    sed -i "s/CASE/${file##*/}/g" "$file"
done < <( find . -type f )
find . -type f |
while IFS= read -r file
do
    awk '{gsub(/CASE/,FILENAME)} 1' "$file" > "${file}.$$" &&
    mv "${file}.$$" "$file"
done
我对shell代码所做的每一次更改都很重要,所以如果您不理解我为什么要更改其中的任何部分,请提问

顺便说一句,如果在进行更改后仍然收到错误消息:

awk: syntax error at source line 1
awk: illegal statement at source line 1
然后,您使用的是旧的、损坏的awk(Solaris上为/usr/bin/awk)。永远不要使用该awk。在Solaris上,请使用/usr/xpg4/bin/awk(如果必须,也可以使用nawk)


警告:如果文件名包含换行符或符号(
&
)或转义数字(例如
\1
),则上述操作将失败。有关详细信息,请参阅。如果有任何问题,请发布一些具有代表性的示例输入和预期输出。

您没有发布任何示例输入和预期输出,因此这只是一个猜测,但可能这就是您想要的:

while read -r file; do 
    sed -i "s/CASE/${file##*/}/g" "$file"
done < <( find . -type f )
find . -type f |
while IFS= read -r file
do
    awk '{gsub(/CASE/,FILENAME)} 1' "$file" > "${file}.$$" &&
    mv "${file}.$$" "$file"
done
我对shell代码所做的每一次更改都很重要,所以如果您不理解我为什么要更改其中的任何部分,请提问

顺便说一句,如果在进行更改后仍然收到错误消息:

awk: syntax error at source line 1
awk: illegal statement at source line 1
然后,您使用的是旧的、损坏的awk(Solaris上为/usr/bin/awk)。永远不要使用该awk。在Solaris上,请使用/usr/xpg4/bin/awk(如果必须,也可以使用nawk)


注意事项:如果您的文件名包含换行符或符号(
&
)或转义数字(例如
\1
),则上述操作将失败。有关详细信息,请参阅。如果有任何问题,请发布一些具有代表性的示例输入和预期输出。

打印第一个脚本中的
是错误

gsub
的第二个参数是替换字符串,而不是命令

您只需要
FILENAME
(注意,不是
“FILENAME”
这是一个文本字符串。
FILENAME
变量。)

请注意,我引用了所有变量,并修复了
find | read
管道,以正确处理名称中包含奇数字符的文件(有关详细信息,请参阅)。我还修复了
mv
命令中错误的

有关如何正确转义原始文件名以使其安全地用于
gsub的替换部分,请参阅上的答案

还请注意,awk的最新版本(我相信是4.1+版本)具有
-I inplace
参数

要修复第二个脚本,需要添加从第一个脚本中删除的引号

for i in *; do awk '{gsub(/CASE/,"'"${i}"'",$0)}' "${i}" > file.txt; done
请注意,我摆脱了使用
ls
(比无用更糟糕,因为它会在文件名中使用空格或shell元字符主动断开文件(有关详细信息,请参阅)

但该命令对于包含各种字符的文件名来说有点难看和不安全,最好按照以下方式编写:

for i in *; do awk -v fname="$i" '{gsub(/CASE/,fname,$0)}' "${i}" > file.txt; done
因为这将正确处理名称中带有双引号/etc的文件名,而直接变量扩展版本则不会


也就是说,更正后的第一个脚本是正确的答案。

print
在第一个脚本中是错误的

gsub
的第二个参数是替换字符串,而不是命令

您只需要
FILENAME
(注意,不是
“FILENAME”
这是一个文本字符串。
FILENAME
变量。)

请注意,我引用了所有变量,并修复了
find | read
管道,以正确处理名称中包含奇数字符的文件(有关详细信息,请参阅)。我还修复了
mv
命令中错误的

有关如何正确转义原始文件名以使其安全地用于
gsub的替换部分,请参阅上的答案

还请注意,awk的最新版本(我相信是4.1+版本)具有
-I inplace
参数

要修复第二个脚本,需要添加从第一个脚本中删除的引号

for i in *; do awk '{gsub(/CASE/,"'"${i}"'",$0)}' "${i}" > file.txt; done
请注意,我摆脱了使用
ls
(比无用更糟糕,因为它会在文件名中使用空格或shell元字符主动断开文件(有关详细信息,请参阅)

但该命令对于包含各种字符的文件名来说有点难看和不安全,最好按照以下方式编写:

for i in *; do awk -v fname="$i" '{gsub(/CASE/,fname,$0)}' "${i}" > file.txt; done
因为这将正确处理名称中带有双引号/etc的文件名,而直接变量扩展版本则不会


也就是说,更正后的第一个脚本是正确的答案。

千万不要对$(ls*)中的i执行
与*
中的i相比,这没有增加任何内容,并引入了可能的错误情况,例如名称中带有空格的文件。此外,awk不是shell-您无法访问awk脚本中的shell变量,就像无法访问C程序中的shell变量一样。有关如何将shell变量的值传递给awk s,请参阅在$(ls*)中,永远不要对i执行
与*
中的i相比,这没有增加任何内容,并引入了可能的错误情况,例如名称中带有空格的文件。此外,awk不是shell-您无法访问awk脚本中的shell变量,就像无法访问C程序中的shell变量一样。有关如何将shell变量的值传递给awk s,请参阅script。我可能会修复find的输出,而不是变量扩展,但是。我肯定您想检查:)@EdMorton,不,是您做的,您让我挠头了?read命令正在读取文件名,而不是文件本身