テーブルのフィールドを表すデータ列を含むフラットファイルがあります。外部ソースからこのファイルをインポートし、データベースのテーブルにデータを挿入しようとしています。残念ながら、私が受け取ったファイルの特定の列にフィールド(新しいフィールドを追加)がありませんでした。私に送信される内容を制御できないので、ファイルを編集してフィールドだけを追加したいと思います。sed
各行の特定の列にテキストを追加するために使用できますか?
たとえば、次のファイルがあるとします。
Alan Bradford 555-2012
Cathy Davies 555-7823
Edward Farris 555-9162
Gary Hobbs 555-5151
Irene Jacobs 555-1285
ファイルに地域番号がないので、213
前に追加したいと思います。電話番号は常に31列(一般文字数)で始まることがわかっています。だから見せたい
Alan Bradford 213 555-2012
Cathy Davies 213 555-7823
Edward Farris 213 555-9162
Gary Hobbs 213 555-5151
Irene Jacobs 213 555-1285
私はこれを3回のパスで行うことができることを知っています。cut -c1-30
パート1を使用して取得でき、cut -c31-
パート2も取得できます。その後、すべて一緒に貼り付けることができます。echo "$Part1 $NEWDATA $Part2" >> filename
sedを使うより簡単な方法があるかどうかを知りたいです。私は次のようなものを使用できるはずです
sed -e "30l,i213 " InFile > OutFile
1行に30文字以上を移動してから213
。
カットして貼り付けるオプションより何が効果があるか、より良いかを知っている人はいますか?
修正する
私は私の例が十分に正確ではなく、人々の時間の無駄を防ぐために質問を編集する必要があると言われました。私が提示した例は、この問題に対して非常に正確です。文字列「XXX」をY位置の前後に置くかどうかにかかわらず、常にY位置に挿入する方法は?
しかし、問題ありません。ここに私の実際のケースがあります。各行には928文字のテキストファイルがあります。 878番位置から文字列を挿入したいと思います。挿入したい位置の後の次のフィールドはメモフィールドなので、通常は空ですが、常に空ではないため、文字列の前と後の値は毎回同じにすることはできません。
@DonHolgoの答えは最も有望で良い答えです。しかし、私が好むUNIX(AIX 7.1)では、エラーが発生する前に最大255文字までしか追跡できないようです。
ここでは、255列に「XXX」を挿入します。
# sed 's/.\{255\}/&XXX /' OrigTextFile
1 030680001001YNPO 14 H502 000595000000000000 1 0000680M00000100000004799000000000000479900000004799000000004799000000000000479900000 SDI42028820 20P561292 00000000000XXX 000000000000000000000000000000000000000000000000000000000000000 T 0000655000000000Y 0000516000000000E 0000280000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 20200814
しかし、256列以上に同じ演算を挿入してみました。
# sed 's/.\{256\}/&XXX /' OrigTextFile
sed: 0602-404 Function s/.\{256\}/&XXX / cannot be parsed.
私のsedバージョンに制限があるようです。したがって、テキストファイルを切り取る元の計画に従う必要があるかもしれません。 File1 = テキストファイルの各行の最初の 878 文字 File2 = 追加する新しい文字列、元のファイルの 1 行に 1 つずつ File3 = 元のテキストファイルの残りの文字。
それから参加してください:
# paste File1 File2 File3 > NewTextFile
答え1
あなたはそれを使用することができます
sed 's/.\{30\}/&213 /' InFile > OutFile
最初の30文字(「すべての文字」×30)をそれ自体(&
)+「213」に置き換えます。
答え2
計算REを使用できます。たとえば、x{12}
12x
文字が一致し、y{1,3}
1、2、または3y
文字が一致します。ここでは.{30}
、30文字(つまり任意の30文字)に一致するワイルドカードを使用します。結果\1
文字列のパターンマッチングで括弧で囲まれた参照と一致します。
sed -r 's#^(.{30})#\1213 #' file
更新された質問では、挿入する前に878文字があると言います。したがって、例の30を実際には878に変更して挿入するだけです。XXX
sed -r 's#^(.{878})#\1XXX#' file
固定幅の変更にも同じプロセスを適用できます。
perl
いくつかの実装を悩ませる行の長さに制限がないものを使用することもできますsed
。
perl -pe 's#^(.{878})#$1XXX#' file
答え3
以下を試すこともできます。awk
awk '{sub(/^.{30}/,"&213 ")}1' file
213
これは行の最初の30文字のパターンに追加されます。
構文は次のとおりです。
- この
sub()
機能は置き換えに使用されます。最初指定された正規表現は、現在の行(または機能するように明示的に指定された文字列がない場合はデフォルトの宛先)に表示されます。 - 正規表現は
^.{30}
「すべての文字30番」を意味しますが、行の先頭から始まります(「アンカー」を意味^
)。 - 代替は、「発見されたパターン(の意味)とスペースが
&
続くことです。213
213
行の残りの部分は変更されず、最初の30文字の後に挿入されます。
これはすべての行で実行されます({ ... }
無条件の作業ブロック)。これにより、awk
修正された行(プログラムの1
終わりawk
)が印刷されます。
答え4
ツールの外部限界に達したら、877 の数値を 3 つの単位、つまり 255 と残りの 112 に分けることができます。
skip=877
cmax=255
mult=`expr "$skip" / "$cmax"`
rem=`expr "$skip" % "$cmax"`
lim=".\\{$cmax\\}"
re="\\($lim\\)\\{$mult\\}.\\{$rem\\}"
sed -e "s/$re/&XXX/" your_file_nam
より簡単な方法は以下を使用することですPerl
。
perl -lpe 'substr($_, 877) =~ s/^/XXX/' your_file_name
Python:
python3 -c '
import sys
f, p, r = sys.argv[1:]
p = int(p)
with open(f) as fh:
print(*[l[:p]+r+l[p:] for l in fh],sep="",end="")
' file_name 877 "XXX"