私の最初のファイルには、screen.txt
次の単一文字が含まれています。
d
m
a
o
2番目のファイルbeta.txt
には複数行が含まれています。
cvvbbe
etgjiua
qwrfggo
3番目のファイルgama.sh
はシェルスクリプトです。
beta.txt
次のようにファイルを繰り返す必要があります。
- 各行の最後の文字を
beta.txt
最初の文字に置き換えます。screen.txt
- 救う
beta.txt
- 走る
gama.sh
- 各行の最後の文字を
beta.txt
2番目の文字に置き換えます。screen.txt
- 救う
beta.txt
- 走る
gama.sh
- など。
答え1
awkを使用してください。
$ cat gama.sh
#!/usr/bin/env sh
awk '
NR==FNR {
beta[++nr] = substr($0,1,length($0)-1)
next
}
{
for ( i=1; i<=nr; i++ ) {
print beta[i] $0 > ARGV[1]
}
print "" > ARGV[1]
}
' "$@"
$ ./gama.sh beta.txt screen.txt
$ cat beta.txt
cvvbbd
etgjiud
qwrfggd
cvvbbm
etgjium
qwrfggm
cvvbba
etgjiua
qwrfgga
cvvbbo
etgjiuo
qwrfggo
上記は、内容がbeta.txt
メモリに収まらないほど大きくないと仮定しています。それ以外の場合は、内容がscreen.txt
メモリに収まる場合:
$ cat gama.sh
#!/usr/bin/env sh
tmp=$(mktemp) &&
awk '
BEGIN { OFS="\t" }
NR==FNR {
screen[++nr] = $0
next
}
{
$0 = substr($0,1,length($0)-1)
for ( i=1; i<=nr; i++ ) {
print i, FNR, $0 screen[i]
}
}
END {
for ( i=1; i<=nr; i++ ) {
print i, FNR+1
}
}
' "$@" |
sort -k1,2n |
cut -f3- > "$tmp" &&
mv -- "$tmp" "$2"
$ ./gama.sh screen.txt beta.txt
$ cat beta.txt
cvvbbd
etgjiud
qwrfggd
cvvbbm
etgjium
qwrfggm
cvvbba
etgjiua
qwrfgga
cvvbbo
etgjiuo
qwrfggo
2番目のスクリプトは、DSU(装飾/整列/装飾解除)イディオムを適用して、目的の順序で出力ラインを生成します。https://stackoverflow.com/questions/71691113/how-to-sort-data-based-on-the-value-of-a-column-for-part-multiple-lines-of-af/71694367#71694367もっと学ぶ。
答え2
sed
次のループで実行できます。
$ while read letter; do
printf '%s\n\n' "$(sed "s/.$/$letter/" beta.txt)";
done < screen.txt > tmpFile && mv tmpFile beta.txt
$ cat beta.txt
cvvbbd
etgjiud
qwrfggd
cvvbbm
etgjium
qwrfggm
cvvbba
etgjiua
qwrfgga
cvvbbo
etgjiuo
qwrfggo
スクリプトで必要に応じて、次のように保存できますgamma.sh
。
#!/bin/sh
tmpFile=$(mktemp)
while read letter; do
printf '%s\n\n' "$(sed "s/.$/$letter/" beta.txt)";
done < screen.txt > "$tmpFile" && mv tmpFile
これは、大容量ファイルの場合は非常に遅くて実用的ではありません。提供されたダミーの例では問題ありませんが、何千行も何百行も処理する必要がある場合は、別の言語を使用する必要があります。たとえば、Perlでは次のようになります。
#!/usr/bin/perl
use strict;
use warnings;
my @letters;
open(my $letterFile, '<', "$ARGV[0]") or
die("Failed to open letter file '$ARGV[0]':$!\n");
while (my $line = <$letterFile>) {
chomp($line);
$line =~ /(.)\s*$/;
push @letters, $1;
}
close($letterFile);
open(my $dataFile, '<', "$ARGV[1]") or
die("Failed to open data file '$ARGV[1]':$!\n");
my @data = <$dataFile>;
my $c = 0;
foreach my $letter (@letters) {
print "\n" if $c;
foreach my $line (@data) {
$line =~ s/.$/$letter/;
print "$line";
}
$c++;
}
close($dataFile);
上記のスクリプトを次のように保存するとfoo.pl
:
$ perl foo.pl screen.txt beta.txt
cvvbbd
etgjiud
qwrfggd
cvvbbm
etgjium
qwrfggm
cvvbba
etgjiua
qwrfgga
cvvbbo
etgjiuo
qwrfggo
これはすべてをbeta.txt
メモリに保存するため、大容量ファイルの場合は問題になる可能性があります。これが問題であれば、別のアプローチが必要ですが、これは現在の質問の範囲外です。