web-dev-qa-db-ja.com

シェルスクリプトを使用して、指定されたパターンの後にファイルに複数の行を挿入します

シェルスクリプトを使用してファイルに複数の行を挿入したい。私の入力ファイルの内容を考えてみましょう:input.txt:

abcd
accd
cdef
line
web

input.txtファイルの行「cdef」の後に4行を挿入する必要があります。ファイルを挿入すると、次のように変わります。

abcd
accd
cdef
line1
line2
line3
line4
line
web

上記の挿入は、シェルスクリプトを使用して行う必要があります。誰でも私を助けることができますか?

59
user27

別のsed

sed '/cdef/r add.txt' input.txt

input.txt:

abcd
accd
cdef
line
web

add.txt:

line1
line2
line3
line4

テスト:

sat:~# sed '/cdef/r add.txt' input.txt
abcd
accd
cdef
line1
line2
line3
line4
line
web

input.txtファイルの変更を適用する場合。次に、-isedとともに使用します。

sed -i '/cdef/r add.txt' input.txt

正規表現を式として使用するには、-Eタグとsedを使用する必要があります。

sed -E '/RegexPattern/r add.txt' input.txt
82
sat

GNU sedを使用:

sed "/cdef/aline1\nline2\nline3\nline4" input.txt

で始めた場合:

abcd
accd
cdef
line
web

これは以下を生成します:

abcd
accd
cdef
line1
line2
line3
line4
line
web

ファイルへの変更をその場で保存する場合は、次のように言います。

sed -i "/cdef/aline1\nline2\nline3\nline4" input.txt
30
devnull
sed '/^cdef$/r'<(
    echo "line1"
    echo "line2"
    echo "line3"
    echo "line4"
) -i -- input.txt
16

awkを使用:

awk '/cdef/{print $0 RS "line1" RS "line2" RS "line3" RS "line4";next}1' input.txt 

説明:

  • /.../を使用して、挿入する行を見つけます
  • print $0を使用して現在の行を印刷します
  • RSは組み込みのawk変数で、デフォルトではnew-lineに設定されます。
  • この変数で区切られた新しい行を追加します
  • 最後の1は、1行おきに印刷されます。 nextを使用する前に、print $0を使用してすでに印刷しているため、現在の行を防止できます。
$ awk '/cdef/{print $0 RS "line1" RS "line2" RS "line3" RS "line4";next}1' input.txt
abcd
accd
cdef
line1
line2
line3
line4
line
web

ファイルに変更を加えるには、次のことができます。

awk '...' input.txt > tmp && mv tmp input.txt
13
jaypal singh

この答えは理解しやすいです

  • パターンの前にコピー
  • 行を追加
  • パターンの後にコピー
  • 元のファイルを置き換える

    FILENAME = 'app/Providers/AuthServiceProvider.php'

ステップ1パターンまでコピー

sed '/THEPATTERNYOUARELOOKINGFOR/Q' $FILENAME >>${FILENAME}_temp

ステップ2行を追加する

cat << 'EOL' >> ${FILENAME}_temp

HERE YOU COPY AND
PASTE MULTIPLE
LINES, ALSO YOU CAN
//WRITE COMMENTS

AND NEW LINES
AND SPECIAL CHARS LIKE $THISONE

EOL

ステップ3ファイルの残りを追加します

grep -A 9999 'THEPATTERNYOUARELOOKINGFOR' $FILENAME >>${FILENAME}_temp

元のファイルを置き換える

mv ${FILENAME}_temp $FILENAME

変数が必要な場合は、ステップ2で「EOL」をEOLに置き換えます

cat << EOL >> ${FILENAME}_temp

this variable will expand: $variable1

EOL
1
lalo

最小限のツールでいくつかのファイルをテンプレート化する必要がありましたが、上記のsed -e '/../r file.txtの問題は、一致の残りを印刷した後にファイルを追加するだけで、置き換えないことです。

これは行いません(すべての一致が置き換えられ、パターンマッチングは同じポイントから続行されます)

#!/bin/bash

TEMPDIR=$(mktemp -d "${TMPDIR:-/tmp/}$(basename $0).XXXXXXXXXXXX")
# remove on exit
trap "rm -rf $TEMPDIR" EXIT

DCTEMPLATE=$TEMPDIR/dctemplate.txt
DCTEMPFILE=$TEMPDIR/dctempfile.txt

# template that will replace
printf "0replacement
1${Shell} data
2anotherlinenoEOL" > $DCTEMPLATE

# test data
echo -e "xxy \n987 \nxx xx\n yz yxxyy" > $DCTEMPFILE

# print original for debug
echo "---8<--- $DCTEMPFILE"
cat $DCTEMPFILE
echo "---8<--- $DCTEMPLATE"
cat $DCTEMPLATE
echo "---8<---"

# replace 'xx' -> contents of $DCTEMPFILE
Perl -e "our \$fname = '${DCTEMPLATE}';" -pe 's/xx/`cat $fname`/eg' ${DCTEMPFILE}
0
Pasi Savolainen

awkを使用して、input.txtの途中にコマンドの出力を挿入できます。
挿入する行は、cat otherfilels -l、またはprintfによって生成された番号を持つ4行の出力です。

awk 'NR==FNR {a[NR]=$0;next}
    {print}
    /cdef/ {for (i=1; i <= length(a); i++) { print a[i] }}'
    <(printf "%s\n" line{1..4}) input.txt
0
Walter A