将文件名的前 5 个字符添加到文件中的每一行

将文件名的前 5 个字符添加到文件中的每一行

我的文件夹中有许多“.txt”文件。

对于每个 .txt 文件,我需要获取文件名中的前 5 个字符,并将它们添加到文件中每行的开头。我还需要在新文件中每行的开头添加一个“*”符号。

我尝试使用以下命令,但它在文件中每行超过一个空格的文件中给出了错误的输出。

awk 'FNR == 1 {chr =substr(FILENAME, 0,5); name = FILENAME ".new" }{ printf("%s %s\n", "*"chr$1, $2) >name}' *.txt 

有人可以修改代码或建议更简单的方法来执行此操作。

答案1

我将使用 shell 循环来迭代文件(这里假设 shell 支持${param:offset:length}ksh93 中的运算符):

for f in *.txt
do
    sed -i -- "s/^/*${f:0:5} /" "$f"
done

(假设文件名不包含反斜杠、换行符或&字符)。

我的偏好是将数据写入一个新文件,当它们全部完成后,然后替换它们全体。这将允许处理中断的进程。但这不是我在这里所做的。

答案2

输出数据时没有理由只处理每行的前两个字段;只需打印$0(整个原始行)即可:

awk '
    FNR == 1 { close(name); chr = substr(FILENAME, 3, 5); name = FILENAME ".new" }
    { printf "*%s %s\n", chr, $0 >name }' ./*.txt

如果您愿意,可以使用print "*" chr, $0 >name它来代替该语句。printf

或者,使用 shell 循环:

for name in *.txt; do
    PREFIX=${name:0:5} awk '{ printf "*%s %s\n", ENVIRON["PREFIX"], $0 }' <"$name" >"$name.new"
done

在这里,我假设您使用的 shell 支持ksh93's${param:offset:length}运算符,例如 , ksh93, bash, zsh, mksh, busybox sh 。与 一起yash使用,${name[1,5]}代替${name:0:5}(也适用于zsh),或 POSIXly:${name%"${name#?????}"}

答案3

使用(以前称为 Perl_6)

~$ raku -e 'for @*ARGS {                                          \ 
                my $str  = .substr(0..4);                         \ 
                my @body = .IO.lines.map({ "*" ~ $str ~ $_ });    \
                spurt($_ ~ "_new", @body.join("\n") ~ "\n" );     \
            };'   *.txt

或者:

~$ raku -e 'for @*ARGS ->  $filename {                                   \
                my $str  = $filename.substr(0..4);                       \
                my @body = $filename.IO.lines.map({ "*" ~ $str ~ $_ });  \
                spurt($filename ~ "_new", @body.join("\n") ~ "\n" )      \
            };'   *.txt  

Raku 是 Perl 家族的一种编程语言。在 Raku 中,@*ARGS是保存 shell 命令行上的参数的数组。简要地:

  • 使用for数组@*ARGS进行迭代,
  • 使用substr每个参数的前 5 个字符(例如文件名,此处为$_$filename)被提取到$str
  • 每个参数(例如文件名)都被转换为一个IO对象并全部lines被读取。行被修改,以便在每行的开头添加 和 ,并且这些修改的行被保存*到,$str@body
  • 输出是通过该spurt()方法创建的,该方法采用文件路径(即新创建的文件的名称),后跟要写入的修改文本(@body),并添加合适的换行符。

示例输入(示例文件名为fileA):

>TCONS_00000867
>TCONS_00001442
>TCONS_00001447
>TCONS_00001528
>TCONS_00001529
>TCONS_00001668
>TCONS_00001921
>TCONS_00001922

示例输出(fileA_new,根据需要修改文本):

*fileA>TCONS_00000867
*fileA>TCONS_00001442
*fileA>TCONS_00001447
*fileA>TCONS_00001528
*fileA>TCONS_00001529
*fileA>TCONS_00001668
*fileA>TCONS_00001921
*fileA>TCONS_00001922

https://course.raku.org/essentials/positionals/args-array/
https://docs.raku.org/language/variables#@*ARGS
https://docs.raku.org/type/independent-routines#sub_spurt
https://raku.org

答案4

在每行前面添加"*<first-5-bytes> "

perl -pi -e '$_ = "*" . substr($ARGV, 0, 5) . " $_"' -- *.txt

要在前面添加前 5 个字符而不是字节,它们本身根据区域设置的字符编码从文件名的字节中解码:

perl -MEncode::Locale -MEncode -pi -e '
  $_ = "*".
       encode(locale => substr(decode(locale_fs => $ARGV), 0, 5)).
       " $_"' -- *.txt

或者避免对每一行执行“decode+substr+encode”操作:

perl -MEncode::Locale -MEncode -pi -e '
  $prefix = "*".
     encode(locale => substr(decode(locale_fs => $ARGV), 0, 5)).
     " $_" if $. == 1;
  $_ = $prefix . $_;
  close ARGV if eof' -- *.txt

áéíóú123.txt例如,对于在 UTF-8 语言环境中调用的文件会产生影响。

即使在一些存在这种区别的非 POSIX 系统中,使用locale_fs而不是也可以使其工作。locale

相关内容