在 for 循环中从模式到文件末尾进行 sed
sed from pattern till end of file inside a for loop
我正在编写一个 bash 脚本,它允许我从一个文件中获取一定数量的文本,并在该文件列表之前添加一些其他文本。
directory=$(pwd)
for f in *test.txt
do
filename=$(basename $f .txt)
printf "%%sum=4 \n"> input.temp
printf "file=$directory"/"$filename".txt" \n">> input.temp
printf "some commands \n">> input.temp
printf "\n" >> input.temp
printf "description \n">> input.temp
sed -n "/0 1/,$p" "$f" >> input.temp;
mv input.temp $filename.temp
done
for 循环中的 sed 命令有问题。我环顾四周,人们建议我添加双引号,但无济于事。我认为它可能是 $p。
我希望这已经足够清楚了。如果不是,我会尽力解释得更好。
sed -n "/0 1/,$p" "$f" >> input.temp;
无效
sed -n '/0 1/,$p' "$f" >> input.temp;
无效
sed -n "/0 1/,$p" "$f" >> input.temp;
无效
仅供参考,我并不是要寻找其他有用的东西。我想修复这个确切的输入。我敢肯定,我听起来像个混蛋。
示例输入
%sum=8
file=otherpath/filename.txt
some other commands
another description
0 1
0.36920852 -0.56246512
0.77541848 0.05756533
2.05409026 0.62333039
2.92655258 0.56906375
2.52034254 -0.05096652
1.24167014 -0.61673008
-0.60708600 -0.99443872
0.10927459 0.09899803
3.90284624 1.00103940
3.18648588 -0.09239788
0.93151968 -1.09013674
2.50047427 1.30468389
2.19361322 2.54108378
3.18742399 0.34152442
3.38679424 1.11276220
1.56936488 3.27250306
1.81754180 4.19564055
1 2 1.5 6
2 3 1.5
3 4
4 5 1.5
5 6 1.5
6 11 1.0
7
8
9
10
11
12
13 16
14
15
16 17
17
我想要的输出基本上是这个文件,从“0 1”到结尾,前面是我放在 printf 中的内容。
更新:如果您有兴趣,tripleee 和 Ed Morton 提供的两个脚本工作得非常好。我的脚本中的问题是我从 sed 行中遗漏了 -i 选项(用于就地)。
sed -n "/0 1/,$p" "$f" >> input.temp
应替换为
sed -ni '/0 1/,$p' "$f"
就像其他人已经评论过的那样,您基本上只需要使用单引号而不是双引号,因为双引号中的 $p
会替换为 shell 变量 p
的值通过 shell,在 sed
执行之前(实际上,可能是一个空字符串)。
但是,您可能还想调查在 sed
中完成所有操作。然后,您可能会坚持使用双引号(因为您确实想要替换其他变量),而是使用反斜杠转义 $p
中的美元符号,以保护它免受 shell.
directory=$(pwd) # just do this once before the loop; the value doesn't change
for f in *text.txt; do
# no braces
filename=$(basename "$f" .txt)
sed -n "1i\
%sum=4\
file=$directory/$filename.txt\
some commands\
\
description
/0 1/,$p" "$f" >inputout.temp2 # no pointless separate temp file
done
实际上,我想您希望输出文件在每次迭代中都不同(也许 "$filename.temp"
而不是?),但是您如何处理这显然取决于您。就像现在一样,该文件将包含上次迭代的输出。
我看到你更新了你的问题并在你的评论中提供了一些额外的信息所以试试这个,使用 GNU awk 4.* for -i inplace
:
awk -i inplace -v directory="$(pwd)" '
FNR==1 {
print "%%sum=4 "
print "file=" directory "/" FILENAME
print "some commands "
print ""
print "description "
found = 0
}
/0 1/ { found = 1 }
found
' *text.txt
如果您没有 GNU awk,那么技术上正确的方法是使用 xargs,但使用 shell 循环进行文件操作(移动)部分更简单:
for file in *test.txt
do
awk -v directory="$(pwd)" '
FNR==1 {
print "%%sum=4 "
print "file=" directory "/" FILENAME
print "some commands "
print ""
print "description "
found = 0
}
/0 1/ { found = 1 }
found
' "$file" > tmp && mv tmp "$file"
done
我正在编写一个 bash 脚本,它允许我从一个文件中获取一定数量的文本,并在该文件列表之前添加一些其他文本。
directory=$(pwd)
for f in *test.txt
do
filename=$(basename $f .txt)
printf "%%sum=4 \n"> input.temp
printf "file=$directory"/"$filename".txt" \n">> input.temp
printf "some commands \n">> input.temp
printf "\n" >> input.temp
printf "description \n">> input.temp
sed -n "/0 1/,$p" "$f" >> input.temp;
mv input.temp $filename.temp
done
for 循环中的 sed 命令有问题。我环顾四周,人们建议我添加双引号,但无济于事。我认为它可能是 $p。 我希望这已经足够清楚了。如果不是,我会尽力解释得更好。
sed -n "/0 1/,$p" "$f" >> input.temp;
无效
sed -n '/0 1/,$p' "$f" >> input.temp;
无效
sed -n "/0 1/,$p" "$f" >> input.temp;
无效
仅供参考,我并不是要寻找其他有用的东西。我想修复这个确切的输入。我敢肯定,我听起来像个混蛋。
示例输入
%sum=8
file=otherpath/filename.txt
some other commands
another description
0 1
0.36920852 -0.56246512
0.77541848 0.05756533
2.05409026 0.62333039
2.92655258 0.56906375
2.52034254 -0.05096652
1.24167014 -0.61673008
-0.60708600 -0.99443872
0.10927459 0.09899803
3.90284624 1.00103940
3.18648588 -0.09239788
0.93151968 -1.09013674
2.50047427 1.30468389
2.19361322 2.54108378
3.18742399 0.34152442
3.38679424 1.11276220
1.56936488 3.27250306
1.81754180 4.19564055
1 2 1.5 6
2 3 1.5
3 4
4 5 1.5
5 6 1.5
6 11 1.0
7
8
9
10
11
12
13 16
14
15
16 17
17
我想要的输出基本上是这个文件,从“0 1”到结尾,前面是我放在 printf 中的内容。
更新:如果您有兴趣,tripleee 和 Ed Morton 提供的两个脚本工作得非常好。我的脚本中的问题是我从 sed 行中遗漏了 -i 选项(用于就地)。
sed -n "/0 1/,$p" "$f" >> input.temp
应替换为
sed -ni '/0 1/,$p' "$f"
就像其他人已经评论过的那样,您基本上只需要使用单引号而不是双引号,因为双引号中的 $p
会替换为 shell 变量 p
的值通过 shell,在 sed
执行之前(实际上,可能是一个空字符串)。
但是,您可能还想调查在 sed
中完成所有操作。然后,您可能会坚持使用双引号(因为您确实想要替换其他变量),而是使用反斜杠转义 $p
中的美元符号,以保护它免受 shell.
directory=$(pwd) # just do this once before the loop; the value doesn't change
for f in *text.txt; do
# no braces
filename=$(basename "$f" .txt)
sed -n "1i\
%sum=4\
file=$directory/$filename.txt\
some commands\
\
description
/0 1/,$p" "$f" >inputout.temp2 # no pointless separate temp file
done
实际上,我想您希望输出文件在每次迭代中都不同(也许 "$filename.temp"
而不是?),但是您如何处理这显然取决于您。就像现在一样,该文件将包含上次迭代的输出。
我看到你更新了你的问题并在你的评论中提供了一些额外的信息所以试试这个,使用 GNU awk 4.* for -i inplace
:
awk -i inplace -v directory="$(pwd)" '
FNR==1 {
print "%%sum=4 "
print "file=" directory "/" FILENAME
print "some commands "
print ""
print "description "
found = 0
}
/0 1/ { found = 1 }
found
' *text.txt
如果您没有 GNU awk,那么技术上正确的方法是使用 xargs,但使用 shell 循环进行文件操作(移动)部分更简单:
for file in *test.txt
do
awk -v directory="$(pwd)" '
FNR==1 {
print "%%sum=4 "
print "file=" directory "/" FILENAME
print "some commands "
print ""
print "description "
found = 0
}
/0 1/ { found = 1 }
found
' "$file" > tmp && mv tmp "$file"
done