2つのテキストファイルと1つのシェルスクリプトを繰り返す必要があります。

2つのテキストファイルと1つのシェルスクリプトを繰り返す必要があります。

私の最初のファイルには、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.txt2番目の文字に置き換えます。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メモリに保存するため、大容量ファイルの場合は問題になる可能性があります。これが問題であれば、別のアプローチが必要ですが、これは現在の質問の範囲外です。

関連情報