Если вы не против экспортировать переменную в свою среду, вы можете использоватьenvsubst
:
NAME
envsubst - substitutes environment variables in shell format strings
SYNOPSIS
envsubst [OPTION] [SHELL-FORMAT]
DESCRIPTION
Substitutes the values of environment variables.
Пр. дано
$ cat foo
foo ${bar}
, затем
$ export bar="foo"
$ envsubst < foo
foo foo
Хотяtr
является правильным инструментом для этой работы , вы можете сделать это в sed
, используя командуy
(транслитерации ), а не командуs
(замены ):
$ echo '111111100000000000000' | sed 'y/01/10/'
000000011111111111111
y
в основном является внутренней реализацией sed
tr
-со всеми вытекающими отсюда накладными расходами.
Для этого можно использовать tr
, его основная цель — перевод символов:
echo 111111100000000000000 | tr 01 10
Ваша команда sed
заменяет все 0 на 1, что приводит к строке, содержащей только 1 с (исходные 1 с и все замененные 0 с ), а затем заменяет все 1 с 0 с, в результате чего строка содержит только 0 с.
В длинных потоках tr
быстрее, чем sed
; для файла размером 100 МиБ:
$ time tr 10 01 < bigfileof01s > /dev/null
tr 10 01 < bigfileof01s > /dev/null 0.07s user 0.03s system 98% cpu 0.100 total
$ time sed y/10/01/ < bigfileof01s > /dev/null
sed y/10/01/ < bigfileof01s > /dev/null 3.91s user 0.11s system 99% cpu 4.036 total
Путь естьecho "111111100000000000000" | sed 's/1/2/g;s/0/1/g;s/2/0/g'
Вероятно, медленный метод, но он делает это бинарным способом, используя встроенную оболочку -в арифметике:
echo '111111100000000000000' |
while read -rn1 b; do
printf '%1d' $((b^1))
done
Или для обработки двоичного потока по байтовым фрагментам:
#!/usr/bin/env bash
# Populate a byte to inverted binary string array
declare -a byte_binstring=()
for ((byte=0; byte<=255; byte++)); do
for ((bit=0; bit<=7; bit++)); do
printf -v byte_binstring[byte] '%1s' "$((!(byte>>bit&1)))${byte_binstring[byte]}"
done
done
# Read input stream by chunks of 8 bits max
while read -rn8 bin_str; do
# $((2#$bin_str)) converts the bit string into a byte value
# using shell built-in base-2 arithmetic conversion
# byte_binstring[$((2#$bin_str))] gets the string matching this byte value
# ${#bin_str}} gives the number of bits read (string length)
# extract the last n characters from string matching
# number of byte read
# ${byte_binstring[$((2#$bin_str))]: -${#bin_str}}
# This prints the inverted binary representation from the read bits stream
printf '%s' "${byte_binstring[$((2#$bin_str))]: -${#bin_str}}"
done
Если ваша строка содержит только одну строку и состоит только из 0 и 1, вы можете использовать это
echo "111111100000000000000" |
perl -e 'while (read(STDIN, $b, 1)) { print chr(ord($b) ^ 1); } print "\n";'
Если строка может содержать несколько строк, просто измените perl -e
на perl -ne
и измените способ чтения байтов (, так как read
нужен дескриптор файла)
echo -e "111111100000000000000\n0001111010101" |
perl -ne 'while (/(.)/g) { print chr(ord($1)^1) } print "\n"'
Однако таким образом каждая строка разбивается на строку, поэтому для больших файлов это может быть не очень эффективно. В этом случае необходима небольшая проверка
echo "122111111034000000000abc0000" | perl -e 'while (read(STDIN, $b, 1)) {
print ($b eq '0' or $b eq '1' ? chr(ord($b) ^ 1) : $b) } print "\n";'
Как видите, этот способ работает и для строк, содержащих символы, отличные от '0'
и '1'