私のフォルダには「.txt」ファイルがたくさんあります。
各 .txt ファイルのファイル名の最初の 5 文字を取得し、ファイルの各行の先頭に追加する必要があります。また、新しいファイルの各行の先頭に「*」記号を追加する必要があります。
次のコマンドを試してみましたが、1行に1つの空白が複数あるファイルで誤った出力が発生しました。
awk 'FNR == 1 {chr =substr(FILENAME, 0,5); name = FILENAME ".new" }{ printf("%s %s\n", "*"chr$1, $2) >name}' *.txt
誰かがコードを修正したり、これを行うより簡単な方法を提案できますか?
答え1
シェルループを使用してファイルを繰り返します(シェルが${param:offset:length}
ksh93の演算子をサポートしているとします)。
for f in *.txt
do
sed -i -- "s/^/*${f:0:5} /" "$f"
done
(ファイル名にバックスラッシュ、改行文字、または&
文字が含まれていないと仮定)。
私が好むのは、データがすべて完了したら、新しいファイルにデータを書き込んでから置き換えることです。みんな。これにより、中断されたプロセスを処理できます。しかし、それは私がここでやっていることではありません。
答え2
データを出力するときに各行の最初の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
またはシェルループを使用してください。
for name in *.txt; do
PREFIX=${name:0:5} awk '{ printf "*%s %s\n", ENVIRON["PREFIX"], $0 }' <"$name" >"$name.new"
done
ここでは、使用中のシェルが、、、、、busybox sh などksh93
の演算子をサポートすると仮定します。 (とも連携)またはPOSIXly:代わりに使用されます。${param:offset:length}
ksh93
bash
zsh
mksh
yash
${name[1,5]}
${name:0:5}
zsh
${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
シェルコマンドラインに引数を格納する配列です。簡単に:
for
配列を使用して@*ARGS
繰り返します。- 各引数(ファイル名、here、または)
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/言語/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