Learning Platform
Глоссарий Troubleshooting
Урок 09.05 · 22 мин
Средний
trpastecommdiffSet operations

tr: транслитерация и удаление символов

tr (translate or delete characters) — character-by-character трансформация. Не работает с строками, не с regex — только с символами. Принимает stdin, пишет на stdout.

$ echo "hello" | tr 'a-z' 'A-Z'
HELLO

$ echo "hello world" | tr ' ' '_'
hello_world

$ echo "hello123" | tr -d '0-9'
hello

$ echo "aaabbbccc" | tr -s 'a-z'
abc            # -s = squeeze repeats
Опции tr

Каждая опция — простое посимвольное действие.

tr SET1 SET2заменить символы из SET1 на соответствующие из SET2Маппинг 'a-z' -> 'A-Z' заменит каждую строчную на заглавную. Если SET1 длиннее — лишние мапятся на последний символ SET2.
tr -d SETудалить все символы из SETtr -d '0-9' удалит все цифры. Полезно для очистки данных.
tr -s SETsqueeze — соседние повторы -> одинtr -s ' ' заменит multiple spaces на single. Часто для очистки whitespace перед awk.
tr -c SETcomplement — все символы НЕ из SETtr -cd 'a-zA-Z0-9' — удалить всё, кроме alphanumeric. Идеальный sanitizer.

Канонические использования

# Заменить запятые на табы (CSV -> TSV)
$ tr ',' '\t' < orders.csv > orders.tsv

# Удалить carriage returns (Windows -> Unix line endings)
$ tr -d '\r' < windows_file.txt > unix_file.txt

# Слова на отдельных строках (для wc/sort)
$ echo "hello world foo bar" | tr ' ' '\n'
hello
world
foo
bar

# Lowercase
$ echo "HELLO" | tr 'A-Z' 'a-z'
hello

# Squeeze multiple spaces
$ echo "hello   world    !" | tr -s ' '
hello world !

# Только digits и буквы (удалить punctuation)
$ echo "hello, world!" | tr -cd '[:alnum:]\n'
helloworld

[:alnum:], [:digit:], [:space:] — POSIX character classes. Удобно с tr -c для sanitization.

Tr НЕ умеет

  • Multi-character substitution (tr 'foo' 'bar' не заменит ‘foo’ на ‘bar’ — это посимвольная замена f->b, o->a, o->r).
  • Regex.
  • Conditional transformation.

Для multi-char — используй sed.

paste: column merge

paste склеивает строки по горизонтали: берёт строку N из каждого файла и соединяет в одну строку через TAB.

$ cat names.txt
alice
bob
carol

$ cat ages.txt
30
25
28

$ paste names.txt ages.txt
alice   30
bob     25
carol   28

С -d разделитель:

$ paste -d ',' names.txt ages.txt
alice,30
bob,25
carol,28

С -s (serial) — собрать все строки одного файла в одну, разделяя через TAB или -d:

$ paste -s -d ',' names.txt
alice,bob,carol

DE-сценарии paste

# Создать CSV из отдельных колонок
$ paste -d ',' headers.txt names.txt ages.txt > data.csv

# Превратить список строк в comma-separated:
$ paste -s -d ',' tags.txt
sql,python,airflow,kafka

# Объединить два sorted-файла по строкам:
$ paste file1.sorted file2.sorted | awk -F'\t' '{print $1, $2}'

comm: set operations на отсортированных файлах

comm сравнивает два отсортированных файла построчно и выводит три колонки:

  1. строки только в file1
  2. строки только в file2
  3. строки в обоих (common)
$ cat file1.sorted
apple
banana
cherry

$ cat file2.sorted
banana
cherry
date

$ comm file1.sorted file2.sorted
apple
        banana
        cherry
                date

(Здесь tab indent показывает, в какой колонке строка.)

Фильтр через флаги:

  • -1 подавляет колонку 1
  • -2 подавляет колонку 2
  • -3 подавляет колонку 3

Канонические использования:

# Общие строки (intersection)
$ comm -12 file1.sorted file2.sorted

# Только в file1 (difference: A - B)
$ comm -23 file1.sorted file2.sorted

# Только в file2
$ comm -13 file1.sorted file2.sorted

# Уникальные строки одного из файлов (symmetric difference)
$ comm -3 file1.sorted file2.sorted

DE-сценарии comm

1. Новые users сегодня (которых не было вчера)

$ comm -13 <(sort users_yesterday.txt) <(sort users_today.txt)
new_alice
new_bob

<(...)process substitution (про это в модуле 9). Запускает команду как файл — комфортно, когда сортировка нужна на лету.

2. Удалённые users (были вчера, нет сегодня)

$ comm -23 <(sort users_yesterday.txt) <(sort users_today.txt)
gone_carol

3. Common между двумя dataset

# Users, которые были и вчера и сегодня:
$ comm -12 <(sort users_yesterday.txt) <(sort users_today.txt)

4. Set difference — для data quality

# Проверка: все expected files есть в actual:
$ comm -23 <(sort expected.txt) <(sort actual.txt)
# Если вывод пуст — все expected присутствуют в actual
# Если есть строки — это missing files
SQL INTERSECT и EXCEPT — set-операции на уровне запросов

Comm требует sorted input

Без sort:

$ comm file1 file2
comm: file 1 is not in sorted order

Возможны два пути: pre-sort через sort или используй <(sort ...) inline. Или sort -u если хочешь скрытно убрать дубликаты.

# Inline sort:
$ comm -12 <(sort file1) <(sort file2)

# С удалением дубликатов:
$ comm -12 <(sort -u file1) <(sort -u file2)

diff: line-by-line сравнение

diff — про что-то другое: показывает построчные изменения между двумя файлами. Используется для патчей, code review, версионирования.

$ cat v1.txt
line1
line2
line3

$ cat v2.txt
line1
line2-modified
line4

$ diff v1.txt v2.txt
2c2
< line2
---
> line2-modified
3c3
< line3
---
> line4

Формат вывода:

  • 2c2 — строка 2 файла1 changed на строку 2 файла2
  • < — строка из файла1
  • > — строка из файла2

Полезные опции:

git diff — unified format и patch workflow
$ diff -u v1.txt v2.txt    # unified format (для git patches)
$ diff -y v1.txt v2.txt    # side-by-side
$ diff -r dir1 dir2        # рекурсивно по директориям
$ diff -q dir1 dir2        # quiet — только сообщает 'files differ'
$ diff --brief             # эквивалент -q
$ diff --color=auto        # с цветами (GNU diff)

DE-применения diff

# Что изменилось в exported данных
$ diff snapshot_v1.csv snapshot_v2.csv | head -30

# Сравнение конфигов между серверами
$ ssh prod cat /etc/airflow.cfg | diff - /local/airflow.cfg

DE-pipeline: find new rows since last run

# Сегодняшний и вчерашний дамп users:
$ comm -13 <(sort yesterday.csv) <(sort today.csv) > new_users.csv

# Затем — обработка:
$ wc -l new_users.csv
142 new_users.csv

# Для упомянутого dataset из урока (orders.csv):
$ comm -13 <(sort yesterday_orders.csv) <(sort today_orders.csv) \
    | tee new_orders.csv \
    | awk -F',' '{sum+=$3} END {print "New orders sum:", sum}'

Это incremental loading pattern: каждый день обрабатывать только новые строки.

Попробуй сам

  1. Lower->upper:
    echo "hello" | tr 'a-z' 'A-Z'
  2. Удалить цифры:
    echo "abc123def456" | tr -d '0-9'
    # -> abcdef
  3. Sanitize input — только alphanumeric:
    echo "hello, world! 123 @ #" | tr -cd '[:alnum:][:space:]'
  4. Two-file diff:
    printf "a\nb\nc\n" > /tmp/f1
    printf "a\nB\nc\n" > /tmp/f2
    diff /tmp/f1 /tmp/f2
  5. Set intersection:
    printf "apple\nbanana\ncherry\n" | sort > /tmp/fruits1
    printf "banana\ncherry\ndate\n" | sort > /tmp/fruits2
    comm -12 /tmp/fruits1 /tmp/fruits2
    # -> banana, cherry

macOS-различия

  • tr: BSD tr на macOS имеет небольшие различия — некоторые ranges с UTF-8 работают непредсказуемо. Для гарантии используй LC_ALL=C tr ....
  • paste: идентичен.
  • comm: идентичен. Требует sort с тем же locale (использует strcmp).
  • diff: BSD diff не поддерживает --color=auto — используй GNU diff (brew install diffutils -> gdiff).
Проверка знанийKnowledge check
Что лучше использовать: 'tr' или 'sed' для следующих задач, и почему? (1) Заменить все запятые на табы. (2) Заменить слово 'foo' на 'bar'. (3) Удалить все цифры из строки. (4) Заменить начало строк '#' комментариев на '//'.
ОтветAnswer
(1) Запятые -> табы: ОБА работают. tr ',' '\t' проще и быстрее (посимвольная подстановка, нет regex parser). sed 's/,/\t/g' тоже работает но overkill. Используй tr. (2) 'foo' -> 'bar': только sed. tr — посимвольный, 'tr foo bar' заменит f->b, o->a, o->r (один-в-один по символам), что НЕ заменит слово 'foo' на 'bar'. Нужен sed 's/foo/bar/g'. (3) Удалить цифры: ОБА работают. tr -d '0-9' проще; sed 's/[0-9]//g' тоже. Tr быстрее на больших объёмах. (4) Начало строк '#' -> '//': только sed. tr не понимает якорей (^,$) и multi-char replacement. sed 's/^#/\/\//' — два символа на два символа, нужны якоря. Главное правило: tr — для character-level transformations (lowercase, удалить класс символов, заменить один символ на другой). sed — для string-level (multi-char, regex, anchors). Если задача — посимвольная мапа — tr быстрее и читаемее; для строк — только sed.

Главное

  • tr SET1 SET2 — посимвольная замена. tr -d SET удалить. tr -s SET squeeze. tr -c SET complement.
  • paste file1 file2 — column merge (TAB separator). paste -d ',' для CSV. paste -s склеить в одну строку.
  • comm file1 file2 (отсортированных) — три колонки: only1, only2, both. Флаги -1/-2/-3 подавляют колонки.
  • Каноны: comm -12 (intersection), comm -23 (only in file1), comm -13 (only in file2).
  • diff file1 file2 — построчное сравнение. -u unified format, -r recursive, -q quiet.
  • comm для set-операций на datasets (incremental loading). diff для patches и code review.
  • Process substitution <(sort file) — sort на лету без temp-файла.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. Команда 'echo foo | tr foo bar' что выведет?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5