在循环中使用 sed -i 时,"sed:无输入文件"



我在其他问题中检查了一些解决方案,但它们不适用于我的案例,我被卡住了,所以我们开始吧。我有一个csv文件,我想将其全部转换为大写。它必须有一个循环,并且至少占用7行代码。我必须使用以下命令运行脚本:

./c_bash.sh student-mat.csv

所以我尝试了这个脚本:

#!/bin/bash
declare -i c=0
while read -r line; do 
if [ "$c" -gt '0' ]; then 
sed -e 's/(.*)/U1/'      
else
echo "$line"
fi
((c++))
done < student-mat.csv

我知道可能有一些不必要的东西,但我想把重点放在sed命令上,因为它看起来像是这里的问题。该脚本显示以下输出:(前5行(:

school,sex,age,address,famsize,Pstatus,Medu,Fedu,Mjob,Fjob,reason,guardian,traveltime,studytime,failures,schoolsup,famsup,paid,activities,nursery,higher,internet,romantic,famrel,freetime,goout,Dalc,Walc,health,absences,G1,G2,G3
GP,F,17,U,GT3,T,1,1,AT_HOME,OTHER,COURSE,FATHER,1,2,0,NO,YES,NO,NO,NO,YES,YES,NO,5,3,3,1,1,3,4,5,5,6
GP,F,15,U,LE3,T,1,1,AT_HOME,OTHER,OTHER,MOTHER,1,2,3,YES,NO,YES,NO,YES,YES,YES,NO,4,3,2,2,3,3,10,7,8,10
GP,F,15,U,GT3,T,4,2,HEALTH,SERVICES,HOME,MOTHER,1,3,0,NO,YES,YES,YES,YES,YES,YES,YES,3,2,2,1,1,5,2,15,14,15
GP,F,16,U,GT3,T,3,3,OTHER,OTHER,HOME,FATHER,1,2,0,NO,YES,YES,NO,YES,YES,NO,NO,4,3,2,1,2,5,4,6,10,10
GP,M,16,U,LE3,T,4,3,SERVICES,OTHER,REPUTATION,MOTHER,1,2,0,NO,YES,YES,YES,YES,YES,YES,NO,5,4,2,1,2,5,10,15,15,15

现在我看到它可以工作了,我想将sed命令永久应用于csv文件,所以我在它后面加了-I:

#!/bin/bash
declare -i c=0
while read -r line; do 
if [ "$c" -gt '0' ]; then 
sed -i -e 's/(.*)/U1/'      
else
echo "$line"
fi
((c++))
done < student-mat.csv

但是输出不是应用更改,而是显示如下:(前5行(

school,sex,age,address,famsize,Pstatus,Medu,Fedu,Mjob,Fjob,reason,guardian,traveltime,studytime,failures,schoolsup,famsup,paid,activities,nursery,higher,internet,romantic,famrel,freetime,goout,Dalc,Walc,health,absences,G1,G2,G3
sed: no input files
sed: no input files
sed: no input files
sed: no input files
sed: no input files

因此,我在互联网上查看了许多不同的解决方案,并尝试将单引号改为双引号。

#!/bin/bash
declare -i c=0
while read -r line; do 
if [ "$c" -gt '0' ]; then 
sed -i -e "s/(.*)/U1/"       
else
echo "$line"
fi
((c++))
done < student-mat.csv

但在这种情况下,它不会应用更改,而是生成一个0字节的文件。所以当我这样做时没有输出:

cat student-mat.csv

我期望的解决方案是,当我应用这个脚本时,它会将所有数据永久更改为大写。在应用脚本后,它应该用命令cat student-mat.csv显示这一点:(前5行(

school,sex,age,address,famsize,Pstatus,Medu,Fedu,Mjob,Fjob,reason,guardian,traveltime,studytime,failures,schoolsup,famsup,paid,activities,nursery,higher,internet,romantic,famrel,freetime,goout,Dalc,Walc,health,absences,G1,G2,G3
GP,F,17,U,GT3,T,1,1,AT_HOME,OTHER,COURSE,FATHER,1,2,0,NO,YES,NO,NO,NO,YES,YES,NO,5,3,3,1,1,3,4,5,5,6
GP,F,15,U,LE3,T,1,1,AT_HOME,OTHER,OTHER,MOTHER,1,2,3,YES,NO,YES,NO,YES,YES,YES,NO,4,3,2,2,3,3,10,7,8,10
GP,F,15,U,GT3,T,4,2,HEALTH,SERVICES,HOME,MOTHER,1,3,0,NO,YES,YES,YES,YES,YES,YES,YES,3,2,2,1,1,5,2,15,14,15
GP,F,16,U,GT3,T,3,3,OTHER,OTHER,HOME,FATHER,1,2,0,NO,YES,YES,NO,YES,YES,NO,NO,4,3,2,1,2,5,4,6,10,10
GP,M,16,U,LE3,T,4,3,SERVICES,OTHER,REPUTATION,MOTHER,1,2,0,NO,YES,YES,YES,YES,YES,YES,NO,5,4,2,1,2,5,10,15,15,15

Sed在文件上工作,而不是在行上。不要读行,在文件上使用sed。Sed可以自己排除第一行。参见sed手册。

您想要:

sed -i -e '2,$s/(.*)/U1/' student-mat.csv

你可以用s/.*/U&/做得更短。


您的代码并不像您想象的那样工作。请注意,您的代码会从输出中删除第二行。您的代码:

  • read -r line读取第一行
  • 打印echo "$line"第一行
  • c++递增
  • read -r line读取第二行
  • 然后sed处理文件的其余部分(从第3行到最后(,并以大写打印
  • 则CCD_ 7递增
  • read -r line失败,循环退出

最新更新