【问题标题】:To replace the first character of the last line of a unix file with the file name用文件名替换 unix 文件最后一行的第一个字符
【发布时间】:2011-12-15 07:33:33
【问题描述】:

我们需要一个 shell 脚本来检索当前目录中的所有 txt 文件,并为每个文件检查它是空文件还是其中包含任何数据(我相信可以使用 wc 命令完成)。

如果它为空则忽略它,因为在我们的情况下,此目录中的所有 txt 文件要么为空,要么包含大量数据,其中文件的最后一行将如下所示:

Z|11|21||||||||||

即最后一行有字符Z,然后是|,然后是an integer,然后是|,然后是an integer,然后是一定数量的|符号。

如果文件不是空的,那么我们只是假设它具有这种格式。最后一行之前的数据是乱码,对我们来说不是必需的,但最后一行之前至少有一行,即如果文件非空,则保证至少有两行。

我们需要一个代码,如果文件不是空的,那么它获取文件,用“filename.txt”替换最后一行的“Z”,并将新数据写入另一个文件,比如 tempfile。因此,最后一行将变为:

filename.txt|11|21|||||||

该行的其余部分保持不变。从 tempfile 中取出最后一行,即 filename.txt|int|int|||||,并合并到 finalfile 中。清除 tempfile 的内容,以便从同一目录中的 next filename.txt 接收数据。 finalfile 具有该目录中所有非空 txt 文件最后几行的编辑版本。

例如:file1.txt 的数据为

....
....
....
Z|1|1|||||

file2.txt 的数据为

....
....
....
Z|2|34|||||

脚本运行后,file1.txt的新数据变为

.....
.....
.....
file1.txt|1|1||||||

这将被写入一个新文件,比如 temp.txt,该文件最初为空。从那里最后一行被合并到一个文件 final.txt 中。所以,final.txt 中的数据是:

file1.txt|1|1||||||

本次合并后,temp.txt中的数据被清空
file2.txt的新数据变成了

...
...
...
file2.txt|2|34||||||

这将被写入同一个文件 temp.txt。最后一行从那里合并到同一个文件 final.txt。
所以,final.txt中的数据是

file1.txt|1|1||||||
file2.txt|2|34||||||

考虑返回的N个文件为txt类型且非空且在同一目录下,final.txt中的数据变为

file1.txt|1|1||||||
file2.txt|2|34||||||
file3.txt|8|3||||||
.......
.......
.......
fileN.txt|22|3|||||

对于某些条件,我已经知道命令,比如
要在文本类型的目录中查找文件,

find <directory> -type f -name "*.txt"  

用于取出最后一行并将其合并到另一个文件中

tail -1 file.txt>>destination.txt

【问题讨论】:

  • 听起来确实像是有人要求 SO 为他们完成工作。如果是这样,您将为解决方案支付多少钱 :) 如果不是,下面是一些基本的 bash 代码。

标签: unix replace filenames


【解决方案1】:

您可以使用“sed”来替换“z”字符。您将处于一个循环中,因此您可以使用其中的文件名。这只是删除 Z,然后回显行和文件名。

祝你好运。

#!/bin/bash
filename=test.txt
line=`tail -1 $filename | sed "s/Z/$filename/"`
echo $line

编辑:

您是否先运行find 命令并查看输出?它当然在每行的开头有一个./。这将破坏 sed,因为 sed 使用 / 作为分隔符。它也不适用于您的问题陈述,它在文件名之前没有额外的“/”。你说的是当前目录,你给出的命令会遍历ALL子目录。尝试简单并使用LS

# `2>/dev/null` puts stderr to null, instead of writing to screen.  this stops
# us getting the "no files found" (error) and thinking it's a file!
for filename in `ls *.txt 2>/dev/null` ; do
    ... stuff ...
done 

【讨论】:

  • find . -type f -name "*.txt" 中的文件名做行=tail -1 $filename|sed "s/Z/$filename/" echo $line done
  • 没有循环,上述命令完美运行。在一个循环中,它不起作用。 for filename in find . -type f -name "*.txt" do line=tail -1 $filename|sed "s/Z/$filename/" echo $line done 输出为: sed: Function s/Z/./bk1.txt/ 无法解析。 sed:函数 s/Z/./bk2.txt/ 无法解析。 sed:函数 s/Z/./bk3.txt/ 无法解析。 Find命令返回文件名为./bk1.txt、./bk2.txt等。在任何地方使用变量filename可以访问文件的内容,但不能用于输入文件名本身
  • 听起来您的文件名包含当前目录“./”
  • 另外,如果你不关心偶尔的错误,你可以写for filename in *.txt ; do。 “;”只是让你把做的事情放在同一行。
猜你喜欢
  • 2015-03-28
  • 1970-01-01
  • 1970-01-01
  • 2021-04-18
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 2021-06-12
  • 2019-12-01
相关资源
最近更新 更多