提问人:Rajasekhar 提问时间:8/21/2023 最后编辑:Charles DuffyRajasekhar 更新时间:8/27/2023 访问量:143
虽然读取循环不忽略与 AWK 正在寻找的模式不匹配的文件
while read loop not ignoring files that don't match pattern that awk is looking for
问:
从下面的文件中,我只想抓取特殊字符“@”之间的模式。但是,我最终会得到不同的结果。
测试文件:.txt
## START :: start of file ##
[email protected]_path@
#
[email protected]_brkr_path@
#
[email protected]_path@
#
path.mw.site[email protected]_brkr_path@
## END :: end of file ##
文本文件中共有 9 行,我的脚本是test_script.sh
#!/bin/bash
while IFS= read -r line; do
pattern1=$(echo "$line" | awk -F '@|@' '{print $2}')
echo $pattern1 one
if [ ! -z "$pattern1" ]; then
echo "pattern is not empty"
fi
done < "$1"
我添加的第一个 echo 语句,用于测试 pattern1 变量中的值。
raj@my_server ~]$ ./test_script.sh testfile.txt
one
mysite.mw_path one
pattern is not empty
one
mysite.mw_brkr_path one
pattern is not empty
one
mysite.mw_path one
pattern is not empty
one
mysite.mw_brkr_path one
pattern is not empty
one
我得到了上面的输出,我期待如下所示的输出
mysite.mw_path one
pattern is not empty
mysite.mw_brkr_path one
pattern is not empty
mysite.mw_path one
pattern is not empty
mysite.mw_brkr_path one
pattern is not empty
感谢这里的帮助。
提前致谢。
答:
3赞
Charles Duffy
#1
让一个 awk 副本完成所有工作要合理得多,而不是为每行输入运行一个单独的 awk 副本;您也可以让自己跳过空行:awk
while IFS= read -r pattern1; do
echo "$pattern1 one"
done < <(awk -F@ '$2 != "" {print $2}')
...它正确地发出:
mysite.mw_path one
mysite.mw_brkr_path one
mysite.mw_path one
mysite.mw_brkr_path one
awk 语句的一般形式是 ;当您跳过 CONDITION 时,它默认对每个输入进行操作,当您跳过 ACTION 时,它默认为 ,但您始终可以同时填写这两个部分。CONDITION { ACTION }
print $0
另请注意,这与 完全相同。-F'@|@'
-F@
评论
0赞
Rajasekhar
8/21/2023
我还有另一种情况,这里的 testfile1 和 testfile3 是相同的,testfile2 有 2 行 mysite.mw_path=/mw/mysite/cfg/DATA1/ mysite.mw_brkr_path=/usr/local/mw/mysite/cfg/DATA2/ test_script.sh testfile1.txt testfile2.txt sed 仅适用于第 2 行while IFS= read -r line; do pattern1=$(echo "$line" | awk -F '@|@' '{print $2}') if [ -n "$pattern1" ]; then pattern2=$(grep "$pattern1" $2 | awk -F"=" '{ print $2 }') sed "s|$pattern1|$pattern2|g" testfile3.txt > output_21aug.txt fi done < "$1"
1赞
Charles Duffy
8/21/2023
我们回答您提出的问题。如果您有新的和不同的问题,请单独提出。
0赞
Rajasekhar
8/21/2023
@CharlesDuffy - 好的,谢谢
1赞
Jay jargot
8/21/2023
#2
要获得所需的输出,必须将以下行移动到块内if [ -z "$pattern1" ]; then
echo $pattern1 one
建议使用 代替 。printf
echo
使用变量时,shell 将执行单词拆分。经常或用于防止这种情况。"${pattern1}"
"$pattern1"
awk
可用于整个文件(编辑):
#!/usr/bin/bash --
while IFS= read -r pattern1 ; do
if [[ -n "${pattern1}" ]] ; then
printf "%s one\npattern is not empty\n" "${pattern1}"
fi
done < <(awk -F '@' '{print $2}' "$1")
评论
0赞
user1934428
8/22/2023
也许更像 bash 的是 ' [ ! -z “${pattern1}” ]'。但你的解决方案当然也是正确的。[[ -n $pattern1 ]]
0赞
Jay jargot
8/22/2023
@user1934428:正确,已修复。感谢。Charles_Duffy提供了性能最高的解决方案。
2赞
user1934428
8/21/2023
#3
我认为为每个输入行启动一个 awk 子进程是矫枉过正的。如果你想读取 bash 中的行,你也可以在 bash 中进行提取。使用变量名称:
if [[ $line =~ @(.*)@ ]]
then
pattern1=${BASH_REMATCH[1]}
[[ -n $pattern1 ]] && echo pattern is not empty
else
echo pattern not found in line "$line"
fi
评论
0赞
Rajasekhar
8/21/2023
我们如何将文件传递到此处以读取该行?
1赞
Charles Duffy
8/21/2023
考虑修复你的引号 () -- 否则,包含字符串的行将在 的输出中将其替换为与 glob 匹配的文件列表。echo "pattern not found in line $line"
*.txt
echo
0赞
user1934428
8/21/2023
@Rajasekhar :这是您在原始代码中已有的内容。我没有看到复制这个的理由,只是发布了我的变体来计算。pattern1
line
0赞
user1934428
8/21/2023
@CharlesDuffy:对;另外,在不加引号的情况下,会将一连串空格压缩到一个空格中。固定。echo
1赞
knittl
8/21/2023
#4
您既不需要 shell 脚本,也不需要循环。只需使用:cut
cut -sd@ -f2 yourfile.txt
或仅与:awk
awk -F@ '/@/{print $2}'
输出:
mysite.mw_path
mysite.mw_brkr_path
mysite.mw_path
mysite.mw_brkr_path
如果你还想用 shell 循环解决问题,你可以直接在 shell 中完成(无需每次都生成进程):awk
#!/bin/sh
while IFS=@ read -r _ pattern1 _; do
if [ -n "$pattern1" ]; then
echo "$pattern1 one"
echo "pattern is not empty"
fi
done < "$1"
(并且没有必要运行它bash
)
评论
0赞
Rajasekhar
8/21/2023
-谢谢你,请在这里帮忙,实际上我问的问题是这个问题的子集,这里是这种情况,这里的 testfile1 和 testfile3 是相同的,testfile2 有 2 行(键值对) mysite.mw_path=/mw/mysite/cfg/DATA1/ mysite.mw_brkr_path=/usr/local/mw/mysite/cfg/DATA2/ test_script.sh testfile1.txt testfile2.txt sed 仅适用于第 2 行while IFS=@ read -r _ pattern1 _; do if [ -n "$pattern1" ]; then pattern2=$(grep "$pattern1" $2 | awk -F"=" '{ print $2 }') sed "s|$pattern1|$pattern2|g" testfile3.txt > output_21aug.txt fi done < "$1"
0赞
knittl
8/21/2023
@Rajasekhar无法阅读评论中发布的代码。如果您有后续问题,请发布一个新问题(并链接现有问题)。shell 脚本可能不是解决您的问题的最佳或最简单的解决方案。您是否考虑过使用 python 或 perl 脚本?
0赞
RARE Kpop Manifesto
8/24/2023
#5
echo '
## START :: start of file ##
[email protected]_path@
#
[email protected]_brkr_path@
#
[email protected]_path@
#
path.mw.site.[email protected]_brkr_path@
## END :: end of file ##'
awk '_<($!NF = $2)' FS='@'
mysite.mw_path
mysite.mw_brkr_path
mysite.mw_path
mysite.mw_brkr_path
评论
@|@
-FS @