シェル組み込み関数

シェル組み込み関数

(UTF-8でエンコードされた)テキストファイルを特定の文字数に切り捨てるには?行の長さは関係なく、単語の途中にカットがあってもいいです。

  • cut1行ずつ作業しているようですが、完全なファイルが必要です。
  • head -c文字以外のバイトを使用してください。

答え1

一部のシステムには、複数のtruncateファイルを切り捨てるコマンドがあります。バイト(文字ではありません)。

perlほとんどのシステムにデフォルトでインストールされている文字を使用できますが、2つ以上の文字に切り捨てられる内容はありません。

真珠

perl -Mopen=locale -ne '
  BEGIN{$/ = \1234} truncate STDIN, tell STDIN; last' <> "$file"
  • の場合、-Mopen=localeロケールの文字概念を使用します(したがって、UTF-8文字セット、つまりUTF-8エンコーディング文字を使用するロケールで)。-CSロケールの文字セットに関係なく、I / OをUTF-8にデコード/エンコードするには、に置き換えます。

  • $/ = \1234:レコード区切り文字を整数への参照として設定します。これは固定長レコード(単位数)を指定する方法です。数値)。

  • 次に、最初のレコードを読み取った後、stdinを所定の位置で切り取り(最初のレコードの終わりに)終了します。

GNU sed

GNUを使用すると、sed次のことができます。 (ファイルにNUL文字や有効な文字を形成しないバイトシーケンスが含まれていないと仮定する場合 - 両方ともテキストファイルに対応する必要があります。)

sed -Ez -i -- 's/^(.{1234}).*/\1/' "$file"

ただし、これはファイル全体を読み取り、メモリに保存してから新しいコピーを書き込むため、はるかに効率的ではありません。

GNU awk

GNUと同じawk

awk -i /usr/share/awk/inplace.awk -v RS='^$' -e '
  {printf "%s", substr($0, 1, 1234)}' -E /dev/null "$file"
  • -e code -E /dev/null "$file"任意のファイル名を渡す方法です。gawk
  • RS='^$':喫煙モード

使用しないでください-i inplace現在の作業ディレクトリから最初に拡張機能をgawkロードしようとすると、誰かがそのディレクトリにマルウェアを植えた可能性があります。システムに付属の拡張プログラムのパスは異なる場合があります。出力を参照してください。inplaceinplaceinplace.awkinplacegawkgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

シェル組み込み関数

ksh93bashまたは使用(コンテンツにNUL​​バイトが含まれていないと仮定し、zshExcept以外のシェルを使用):zsh

content=$(cat < "$file" && echo .) &&
  content=${content%.} &&
  printf %s "${content:0:1234}" > "$file"

そしてzsh

read -k1234 -u0 s < $file &&
  printf %s $s > $file

または:

zmodload zsh/mapfile
mapfile[$file]=${mapfile[$file][1,1234]}

そしてksh93またはbash(参考複数のバージョンのマルチバイト文字で偽でした。bash):

IFS= read -rN1234 s < "$file" &&
  printf %s "$s" > "$file"

ksh93<>;リダイレクト演算子を使用してファイルを書き換えるのではなく、その場所からファイルを切り捨てることもできます。

IFS= read -rN1234 0<>; "$file"

アイコン+ヘッダ

到着印刷UTF32BE最初の1234文字の場合は、/など、文字ごとに固定バイト数を使用するエンコードに変換することも別のオプションですUCS-4

iconv -t UCS-4 < "$file" | head -c "$((1234 * 4))" | iconv -f UCS-4

head -c標準ではありませんが、かなり一般的です。標準に対応するのは、dd bs=1 count="$((1234 * 4))"一度に1バイトを読み、一度に1バイトを書き込むため、効率が悪くなります。iconv標準コマンドですが、エンコード名は標準化されていないため、システムがそうでない可能性があります。UCS-4

ノート

いずれにせよ、出力は最大1234文字まで可能ですが、区切りのない行で終わることができるため、有効なテキストではない可能性があります。

さらに、これらの解決策は文字の中央にあるテキストを切り捨てませんが、文字の中央にあるテキストを破ることができます。文字たとえば、éU + 0065 U + 0301(aeの後に鋭いアクセントの組み合わせ)、または分解された形式の韓国語の音節文字で表されます。


bs1 およびパイプ入力では、GNU 拡張を使用しない限り、1 以外の値は安定して使用できません。パイプを埋めることができるよりもパイプをより早く読み取れば短い読み取りが可能だからiflag=fullblockです。ddiconv

答え2

テキストファイルにUTF-8でエンコードされたUnicodeが含まれていることがわかっている場合は、まずUTF-8をデコードしてUnicode文字エンティティシーケンスを取得して分割する必要があります。

私はこの作業のためにPython 3.xを選択します。

Python 3.x関数の使用開いている()encoding=読むための追加のキーワード引数があります。テキストファイル。方法の説明io.TextIOBase.read()有望に見えます。

したがって、Python 3を使用すると、次のようになります。

truncated = open('/path/to/file.txt', 'rt', encoding='utf-8').read(1000)

明らかに、実際のツールにはコマンドラインパラメータ、エラー処理などが追加されます。

Python 2.xを使用すると、独自のファイルオブジェクトを実装し、入力ファイルを1行ずつデコードできます。

答え3

使用幸せ(以前のPerl6)

RakuはUnicodeの高度な組み込みサポートを提供します。ファイルハンドル名を除いて、文字はUnicodeコンソーシアムの名前に変換されます。標準化されたフォームC(NFC)がデフォルトに設定されています。以下は絵文字の例です。

入力例:

~$ raku -e 'for (0..8) -> $i { $_.[0..$i].join.put given "\x1F600".."\x1F64F"};' > emoticons_0-to-8.txt
~$ cat emoticons_0-to-8.txt

答え4

別の方法を追加したいです。おそらく最高のパフォーマンスを発揮することはできませんが、長いですが、理解しやすいです。

#!/bin/bash

chars="$1"
ifile="$2"
result=$(cat "$ifile")
rcount=$(echo -n "$result" | wc -m)

while [ $rcount -ne $chars ]; do
        result=${result::-1}
        rcount=$(echo -n "$result" | wc -m)
done

echo "$result"

に電話してください$ ./scriptname <desired chars> <input file>

これは目標に達するまで最後の文字を1つずつ削除します。私はこれをより多くの可能性を示すためのアイデアとして提示したかっただけです。

関連情報