使用 Bash 脚本从多个文件中删除前 n 行和 x 列
Deleting first n rows and column x from multiple files using Bash script
我知道 "deleting n rows" 和 "deleting column x" 问题之前都已单独回答过。我目前的问题是,我正在编写我的第一个 bash 脚本,但无法使该脚本按我希望的方式工作。
file0001.csv(一个文件夹里有几百个这样的文件)
Data number of lines 540
No.,Profile,Unit
1,1027.84,µm
2,1027.92,µm
3,1028,µm
4,1028.81,µm
期望的输出
1,1027.84
2,1027.92
3,1028
4,1028.81
我可以单独使用 sed 和 cut,但由于某些原因,以下 bash 脚本没有考虑 cut。它还给我一个错误 "sed: can't read ls: No such file or directory",但 sed 成功并且输出保存到原始文件中。
sem2csv.sh
for files in 'ls *.csv' #list of all .csv files
do
sed '1,2d' -i $files | cut -f '1-2' -d ','
done
实际输出:
1,1027.84,µm
2,1027.92,µm
3,1028,µm
4,1028.81,µm
我知道可能有 awk 单行代码,但我真的很想了解为什么这个特定的 bash 脚本不是预期的 运行。我错过了什么?
sed
的 -i
选项就地修改文件。您到 cut
的管道没有收到任何输入,因为 sed -i
没有产生任何输出。如果没有此选项,sed
会将结果写入标准输出,而不是返回文件,然后您的管道就会工作;但是你必须自己将结果写回原始文件。
此外,单引号会阻止扩展——您 "looping" 覆盖了单个文字字符串 ls *.csv
。您不是 quoting it properly 的事实会导致字符串在 内部 循环中进行通配符扩展。因此,在变量插值之后,您的 sed
命令扩展为
sed -i 1,2d ls *.csv
and then shell 展开 *.csv
因为它没有被引用。 (您应该已经收到警告,指出当前目录中也没有名为 ls
的文件。)您可能试图复制一个使用反引号 (ASCII 96) 而不是单引号 (ASCII 39) 的示例 - - 差别很大。
无论如何,ls
是 useless -- 正确的习语是
for files in *.csv; do
sed '1,2d' "$files" ... # the double quotes here are important
done
混合使用 sed
和 cut
通常不是一个好主意,因为您可以用一个简单的 sed
脚本来表达 cut
可以做的任何事情。所以你的整个脚本可以是
for f in *.csv; do
sed -i -e '1,2d' -e 's/,[^,]*$//' "$f"
done
表示删除最后一个逗号及其后的所有内容。 (如果您的 sed
不喜欢多个 -e
选项,请尝试使用分号分隔符:sed -i '1,2d;s/,[^,]*$//' "$f"
)
你可以用awk,
$ awk 'NR>2{sub(/,[^,]*$/,"",[=10=]);print}' file
1,1027.84
2,1027.92
3,1028
4,1028.81
或
sed -i '1,2d;s/,[^,]*$//' file
1,2d;
用于删除前两行。
s/,[^,]*$//
删除剩余行中的最后一个逗号部分。
我知道 "deleting n rows" 和 "deleting column x" 问题之前都已单独回答过。我目前的问题是,我正在编写我的第一个 bash 脚本,但无法使该脚本按我希望的方式工作。
file0001.csv(一个文件夹里有几百个这样的文件)
Data number of lines 540
No.,Profile,Unit
1,1027.84,µm
2,1027.92,µm
3,1028,µm
4,1028.81,µm
期望的输出
1,1027.84
2,1027.92
3,1028
4,1028.81
我可以单独使用 sed 和 cut,但由于某些原因,以下 bash 脚本没有考虑 cut。它还给我一个错误 "sed: can't read ls: No such file or directory",但 sed 成功并且输出保存到原始文件中。
sem2csv.sh
for files in 'ls *.csv' #list of all .csv files
do
sed '1,2d' -i $files | cut -f '1-2' -d ','
done
实际输出:
1,1027.84,µm
2,1027.92,µm
3,1028,µm
4,1028.81,µm
我知道可能有 awk 单行代码,但我真的很想了解为什么这个特定的 bash 脚本不是预期的 运行。我错过了什么?
sed
的 -i
选项就地修改文件。您到 cut
的管道没有收到任何输入,因为 sed -i
没有产生任何输出。如果没有此选项,sed
会将结果写入标准输出,而不是返回文件,然后您的管道就会工作;但是你必须自己将结果写回原始文件。
此外,单引号会阻止扩展——您 "looping" 覆盖了单个文字字符串 ls *.csv
。您不是 quoting it properly 的事实会导致字符串在 内部 循环中进行通配符扩展。因此,在变量插值之后,您的 sed
命令扩展为
sed -i 1,2d ls *.csv
and then shell 展开 *.csv
因为它没有被引用。 (您应该已经收到警告,指出当前目录中也没有名为 ls
的文件。)您可能试图复制一个使用反引号 (ASCII 96) 而不是单引号 (ASCII 39) 的示例 - - 差别很大。
无论如何,ls
是 useless -- 正确的习语是
for files in *.csv; do
sed '1,2d' "$files" ... # the double quotes here are important
done
混合使用 sed
和 cut
通常不是一个好主意,因为您可以用一个简单的 sed
脚本来表达 cut
可以做的任何事情。所以你的整个脚本可以是
for f in *.csv; do
sed -i -e '1,2d' -e 's/,[^,]*$//' "$f"
done
表示删除最后一个逗号及其后的所有内容。 (如果您的 sed
不喜欢多个 -e
选项,请尝试使用分号分隔符:sed -i '1,2d;s/,[^,]*$//' "$f"
)
你可以用awk,
$ awk 'NR>2{sub(/,[^,]*$/,"",[=10=]);print}' file
1,1027.84
2,1027.92
3,1028
4,1028.81
或
sed -i '1,2d;s/,[^,]*$//' file
1,2d;
用于删除前两行。s/,[^,]*$//
删除剩余行中的最后一个逗号部分。