使用 sed 命令从多个文件中删除行
Removing lines from multiple files with sed command
所以,免责声明:我对使用 bash 和 zsh 还很陌生,所以答案可能真的很简单。尽管如此。我检查了以前的帖子,但找不到任何东西。 (编辑:我在 bash 和 zsh shell 中都尝试过这个——同样的问题。)
我有一个包含许多文件的目录,我正在尝试从每个文件中删除第一行。
假设目录包含:file1.txt file2.txt file3.txt ...等
我正在使用 sed 命令(非 GNU):
sed -i -e "1d" *.txt
出于某种原因,这只是删除了第一个文件的第一行。我认为 *.txt 会影响目录中与模式匹配的所有文件。奇怪的是,它正在创建附加了 -e 的文件副本,但副本和原始文件是相同的。
我用其他命令(例如 ls *.txt)试过了,效果很好。我缺少有关 sed 的内容吗?
提前谢谢你。
- 在没有 -e 的情况下使用它!
一个文件使用:
sed -i '1d' filename
所有文件使用:
sed -i '1d' *.txt
或
files=/path/to/files/*.extension ; for var in $files ; do sed -i '1d' $var ; done
。对我来说,我使用 ubuntu 和基于 debian 的系统,这种方法对我 100% 有效,但对于其他平台我不确定,所以这是另一种方法:
用空模式替换第一行,并删除空行,(双命令):
对于 $(ls /path/to/files/*.txt) 中的文件;做 sed -i "s/$(head -1 "$files")//g" "$files" ; sed -i '/^$/d' "$文件" ;完成
注意:如果您的文件包含启动符“/”,则会报错,因此在这种情况下,sed 命令应如下所示 (sed -i "s[$(head -1 "$files")[[g"
)
希望这就是您要找的:)
不同操作系统的不同版本sed
支持不同的参数。
OpenBSD (5.4) sed
-i
标志不可用。您可以使用以下 /bin/sh
语法:
for i in *.txt
do
f=`mktemp -p .`
sed -e "1d" "${i}" > "${f}" && mv -- "${f}" "${i}"
done
FreeBSD (11-CURRENT) sed
-i
标志需要扩展,即使它是空的。因此必须写成 sed -i "" -e "1d" *.txt
GNU sed
这会查看 -i
之后的参数是否是另一个选项(或者可能是一个命令)。如果是这样,它假定进行了就地修改。如果它看起来是文件扩展名,例如“.bak
”,它会将原来的文件重命名为“.bak
”,然后将其修改为原始文件的名称。
其他平台上可能还有其他变体,但我手头有这三个。
这里的问题是当 sed 打开一个新文件时,行号没有被重置,所以 1
只匹配第一个文件的第一行。
一个解决方案是使用 shell 循环,为每个文件调用一次 sed。 展示了如何以最广泛兼容的方式执行此操作,但如果您有支持 -i
标志的 sed 版本,则可以改为执行此操作:
for i in *.txt; do
sed -i.bak '1d' "$i"
done
可以通过传递一个空后缀来避免创建备份文件,但我个人认为这不是一件坏事。总有一天你会感激的!
您似乎没有使用 GNU 工具,但如果您使用过,我建议您使用 GNU awk 来完成此任务。变量 FNR
在这里很有用,因为它单独跟踪每个文件的记录号,允许您这样做:
gawk -i inplace 'FNR>1' *.txt
使用 inplace
扩展,这允许您从每个文件中删除第一行,只打印 FNR
大于 1 的行。
正在测试:
$ seq 5 > file1
$ seq 5 > file2
$ gawk -i inplace 'FNR>1' file1 file2
$ cat file1
2
3
4
5
$ cat file2
2
3
4
5
你传递给 Sed 的最后一个参数是问题所在
尝试这样的事情。
var=(`find *txt`)
for file in "${var[@]}"
do
sed -i -e 1d $file
done
这对我有用。
所以,免责声明:我对使用 bash 和 zsh 还很陌生,所以答案可能真的很简单。尽管如此。我检查了以前的帖子,但找不到任何东西。 (编辑:我在 bash 和 zsh shell 中都尝试过这个——同样的问题。)
我有一个包含许多文件的目录,我正在尝试从每个文件中删除第一行。
假设目录包含:file1.txt file2.txt file3.txt ...等
我正在使用 sed 命令(非 GNU):
sed -i -e "1d" *.txt
出于某种原因,这只是删除了第一个文件的第一行。我认为 *.txt 会影响目录中与模式匹配的所有文件。奇怪的是,它正在创建附加了 -e 的文件副本,但副本和原始文件是相同的。
我用其他命令(例如 ls *.txt)试过了,效果很好。我缺少有关 sed 的内容吗?
提前谢谢你。
- 在没有 -e 的情况下使用它!
一个文件使用:
sed -i '1d' filename
所有文件使用:
sed -i '1d' *.txt
或
files=/path/to/files/*.extension ; for var in $files ; do sed -i '1d' $var ; done
。对我来说,我使用 ubuntu 和基于 debian 的系统,这种方法对我 100% 有效,但对于其他平台我不确定,所以这是另一种方法:
用空模式替换第一行,并删除空行,(双命令):
对于 $(ls /path/to/files/*.txt) 中的文件;做 sed -i "s/$(head -1 "$files")//g" "$files" ; sed -i '/^$/d' "$文件" ;完成
注意:如果您的文件包含启动符“/”,则会报错,因此在这种情况下,sed 命令应如下所示 (sed -i "s[$(head -1 "$files")[[g"
)
希望这就是您要找的:)
不同操作系统的不同版本sed
支持不同的参数。
OpenBSD (5.4) sed
-i
标志不可用。您可以使用以下 /bin/sh
语法:
for i in *.txt
do
f=`mktemp -p .`
sed -e "1d" "${i}" > "${f}" && mv -- "${f}" "${i}"
done
FreeBSD (11-CURRENT) sed
-i
标志需要扩展,即使它是空的。因此必须写成 sed -i "" -e "1d" *.txt
GNU sed
这会查看 -i
之后的参数是否是另一个选项(或者可能是一个命令)。如果是这样,它假定进行了就地修改。如果它看起来是文件扩展名,例如“.bak
”,它会将原来的文件重命名为“.bak
”,然后将其修改为原始文件的名称。
其他平台上可能还有其他变体,但我手头有这三个。
这里的问题是当 sed 打开一个新文件时,行号没有被重置,所以 1
只匹配第一个文件的第一行。
一个解决方案是使用 shell 循环,为每个文件调用一次 sed。 -i
标志的 sed 版本,则可以改为执行此操作:
for i in *.txt; do
sed -i.bak '1d' "$i"
done
可以通过传递一个空后缀来避免创建备份文件,但我个人认为这不是一件坏事。总有一天你会感激的!
您似乎没有使用 GNU 工具,但如果您使用过,我建议您使用 GNU awk 来完成此任务。变量 FNR
在这里很有用,因为它单独跟踪每个文件的记录号,允许您这样做:
gawk -i inplace 'FNR>1' *.txt
使用 inplace
扩展,这允许您从每个文件中删除第一行,只打印 FNR
大于 1 的行。
正在测试:
$ seq 5 > file1
$ seq 5 > file2
$ gawk -i inplace 'FNR>1' file1 file2
$ cat file1
2
3
4
5
$ cat file2
2
3
4
5
你传递给 Sed 的最后一个参数是问题所在 尝试这样的事情。
var=(`find *txt`)
for file in "${var[@]}"
do
sed -i -e 1d $file
done
这对我有用。