sed "s/\(.*\)/\t\1/" $filename > $sedTmpFile && mv $sedTmpFile $filename
このsedスクリプトは、$filename
のすべての行のフォントにタブを挿入すると予想していますが、そうではありません。何らかの理由で、代わりにtを挿入しています。
sed
のすべてのバージョンが\t
。代わりにリテラルタブを挿入するだけです(押します Ctrl-V それから Tab)。
Bashを使用すると、次のようにプログラムでTAB文字を挿入できます。
TAB=$'\t'
echo 'line' | sed "s/.*/${TAB}&/g"
echo 'line' | sed 's/.*/'"${TAB}"'&/g' # use of Bash string concatenation
@seditは正しい道にありましたが、変数を定義するのは少し厄介です。
これをbashで行う方法は、単一引用符で囲まれた文字列の前にドル記号を置くことです。
$ echo -e '1\n2\n3'
1
2
3
$ echo -e '1\n2\n3' | sed 's/.*/\t&/g'
t1
t2
t3
$ echo -e '1\n2\n3' | sed $'s/.*/\t&/g'
1
2
3
文字列に変数展開を含める必要がある場合は、引用符で囲まれた文字列を次のようにまとめることができます。
$ timestamp=$(date +%s)
$ echo -e '1\n2\n3' | sed "s/.*/$timestamp"$'\t&/g'
1491237958 1
1491237958 2
1491237958 3
Bash $'string'
は「ANSI-C拡張」を引き起こします。そして、それは私たちのほとんどが\t
、\r
、\n
など。 https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html#ANSI_002dC-Quoting
$ 'string'の形式の単語は特別に扱われます。 Wordは、stringに展開され、バックスラッシュでエスケープされた文字がANSI C標準で指定されているように置き換えられます。バックスラッシュエスケープシーケンスが存在する場合、デコードされます...
展開された結果は、ドル記号が存在しないかのように、単一引用符で囲まれます。
個人的には、bashismを回避してもコードが移植可能にならないため、bashを回避するためのほとんどの努力はばかげていると思います。 (コードをbash -eu
bashを避けてsh
[あなたが絶対的なPOSIX忍者でない限り]を使用しようとする場合よりも。)しかし、それについて宗教的な議論をするのではなく、私はあなたにBEST *の答えを与えます。
$ echo -e '1\n2\n3' | sed "s/.*/$(printf '\t')&/g"
1
2
3
*ベストアンサー?はい、ほとんどのアンチバッシュシェルスクリプターがコードで間違ったことの1つの例はecho '\t'
@ robrecord's answer のように。これはGNU echoでは機能しますが、BSD echoでは機能しません。これは http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echoのOpen Groupによって説明されています。 .html#tag_20_37_16 そしてこれは、バシズムを避けようとすることが通常失敗する理由の例です。
Ubuntu 12.04(LTS)のBashシェルで次のようなものを使用しました。
最初が一致したときにtab、secondで新しい行を追加するには:
sed -i '/first/a \\t second' filename
firstをtab、secondに置き換えるには:
sed -i 's/first/\\t second/g' filename
$(echo '\t')
を使用します。パターンを引用符で囲む必要があります。
例えば。タブを削除するには:
sed "s/$(echo '\t')//"
sed
を使用して置換を行う必要はありませんが、実際には、行の前にタブを挿入するだけです。この場合の置換は、特に大きなファイルで作業している場合は特に、印刷する場合と比べて費用のかかる操作です。正規表現ではないので読みやすくなっています。
例:awkを使用する
awk '{print "\t"$0}' $filename > temp && mv temp $filename
BSD sedの代わりに、Perlを使用します。
ct@MBA45:~$ python -c "print('\t\t\thi')" |Perl -0777pe "s/\t/ /g"
hi
sed
は\t
をサポートしていません。また、\n
などの他のエスケープシーケンスもサポートしていません。私が見つけた唯一の方法は、sed
を使用してスクリプトにタブ文字を実際に挿入することでした。
そうは言っても、PerlまたはPythonの使用を検討することもできます。ここに短いPythonすべてのストリーム正規表現に使用することを書いたスクリプトがあります:
#!/usr/bin/env python
import sys
import re
def main(args):
if len(args) < 2:
print >> sys.stderr, 'Usage: <search-pattern> <replace-expr>'
raise SystemExit
p = re.compile(args[0], re.MULTILINE | re.DOTALL)
s = sys.stdin.read()
print p.sub(args[1], s),
if __== '__main__':
main(sys.argv[1:])
他のアプローチ(sed
、AWK
など)に対して、他の人がこれを適切に明確にしたと思います。ただし、私のbash
固有の回答(macOS High SierraおよびCentOS 6/7でテスト済み)は次のとおりです。
1)OPが最初に提案したものと同様の検索と置換の方法を使用したい場合、次のようにPerl
を使用することをお勧めします。 注:正規表現の括弧の前のバックスラッシュは不要であり、このコード行は、Perl
置換演算子で_$1
_よりも_\1
_を使用する方が良い方法を反映しています(例: Perl 5ドキュメント )。
_Perl -pe 's/(.*)/\t$1/' $filename > $sedTmpFile && mv $sedTmpFile $filename
_
2)ただし、 ghostdog74 で指摘されているように、望ましい操作は実際には単純にタブを追加であるため、tmpファイルをinput /ターゲットファイル(_$filename
_)、もう一度Perl
をお勧めしますが、次の変更が必要です:
_Perl -pe 's/^/\t/' $filename > $sedTmpFile && mv $sedTmpFile $filename
## OR
Perl -pe $'s/^/\t/' $filename > $sedTmpFile && mv $sedTmpFile $filename
_
3)もちろん、tmpファイルはsuperfluousであるため、すべてを「インプレース」(_-i
_フラグを追加)して、よりエレガントなワンライナーに単純化することをお勧めします
_Perl -i -pe $'s/^/\t/' $filename
_