2016-06-17 13 views
1

このmakeコマンドを実行して、ディレクトリ内のすべてのcsvファイルの最初の行を置き換えてから、@をカンマで置き換えて他の行に置きたいとします。ディレクトリファイルの先頭行を置換する

2番目のコマンドはうまく動作していますが、最初のコマンドは最初のファイルの行を置き換えます。

誰でも私にその助けを与えることができますか?

csv: 
    $(DOCKER_RUN) npm run csv-generator 
    make format-csv 

format-csv: 
    @sed -i '' '1 s/^.*$$/"bar","repository"/g' $(CURDIR)/foo/npm/*.csv 
    @sed -i '' 's/\(.*\)@/\1","/g' $(CURDIR)/foo/npm/*.csv 
+0

コマンドは今のところうまく見えます – fedorqui

+0

@fedorqui 2番目のファイルは正常に動作し、すべてのファイルが変更されますが、最初のファイルは1つだけ変更されます。最初の1つ=/ –

+0

ダミーファイルに対してテストしたところ、うまくいきました。だから私はエラーを再現することはできません。私たちが助けることができるようにいくつかの[mcve]を追加してください。そうでなければ、私たちはあまり何もできません。 – fedorqui

答えて

3

最初sedコマンドはsedは、システム上(入力ファイル間のラインカウンタをリセットしないと、どちらもしないということである「失敗した」という理由)私のMac OS Xマシン上、コメントを参照してください。

$ cat test1 
a 
b 
g 

$ cat test2 
aa 
bb 
cc 

$ sed -n '=' test1 test2 # the '=' sed command outputs line numbers 
1 
2 
3 
4 
5 
6 

この最初のsedコマンドでは、あなたはそれが何をしたいのかやっていないされている理由、それが唯一の影響最初のファイルの最初の行。

ソリューションは、ファイルをループにし、(Makefileの中にテストされていない)、それらのそれぞれのsedを呼び出す:

findxargsを使用して
@for f in $(CURDIR)/foo/npm/*.csv; do \ 
    sed -i '' '1 s/^.*$$/"bar","repository"/g' $f; \ 
done 

findが拾っていないことを確認してくださいだけで、動作しますフォルダ内のファイルをさらに下に移動します。

EDIT:この回答のコメントを踏まえて、私は完全に複数のファイルにsed -iの使用を避けることをお勧めします、とfor -loopsに両方のステートメントを変換する(このケースでは、彼らは1つのループに崩壊することができます二つの文)を:私の経験で

@for f in $(CURDIR)/foo/npm/*.csv; do \ 
    sed -i '' '1 s/^.*$$/"bar","repository"/g' $f; \ 
    sed -i '' 's/\(.*\)@/\1","/g' $f; \ 
done 

、Makefileの中でfor -loopsを使用してfindxargsを使用する場合と比較してはるかに一般的のようです。これはおそらく、ユニックス間のfindxargsの間の非互換性のためです。明示的なループを使用すると、Makefileを読みやすくすることもできます。

+2

'BSDの 'sed'これはOPとGNUの 'sed'によって明らかに使われています。 GNU 'sed'はファイル間の行番号をリセットして、 'line 1'の操作を各ファイルの1行目に適用します。私はそれを認識していませんでしたが、私のMacで 'sed 'の両方のバージョンをインストールしていることを実証するのは簡単でした。同様にBSD 'sed'は' sed '$ s /.*/ xyz/'* .csv'のような操作を最後のファイルの最後の行だけを扱うものとして扱いますが、GNU' sed'は最後の行にマッチするものとして扱います各ファイルのそれは少なくとも一貫している。 –

+2

違いを考えれば、2つの変種のうちの1つがPOSIXに準拠していない可能性がありますが、POSIXは['sed()']について何を言いますか?(http://pubs.opengroup.org/onlinepubs/9699919799/functions/ sed.html)?答えは次のとおりです:_アドレスは、ファイルの入力ラインを累積的にカウントする10進数、入力の最後の行を扱う '$'文字、または... _ BSD 'sed'はこれを実装し、GNU' sed'はそうではありません。しかし、GNU 'sed'は' -i'フラグを使ってこれを行います( '-i'フラグはPOSIXの一部ではないので、標準ではそれを制御しません)。 GNUの実装は理にかなっています。 –

+0

状況はそれほど明確ではありません。 'sed'の[FreeBSD 11](http://www.unix.com/man-page/FreeBSD/1/sed/)のマニュアルページによると、' -i'オプションは行数をリセットします。 –

1

私は解決するために管理:

@find $(CURDIR)/foo/npm -name "*.csv" -type f | xargs -L 1 sed -i '' '1 s/^.*$$/"bar"/g' 
+1

ファイルごとにコマンドを1回実行するときは、ここで 'xargs'は必要ありません。 'find $(CURDIR)/ foo/npm -name" .csv "-type f -exec sed -i '"' 1s /^.*$$/ "bar"/g '{} \; '実行するには'find'から' sed'を直接実行します。これは、スペースなどを含むファイル名に対して正しく働くことの副次的な利点があります( '$$'はそれが '$'と解釈されるので必要です)。 –

関連する問題