You can't use NUL
as argument in bash
You can't use $'\0'
as an argument, store it as a variable or using command substitution $(printf '\0')
since bash
(and most shells?) use C-strings that are null terminated. The leading string before NUL
is interpreted as the string and the trailing string discarded.
You can only input using pipes - printf '\0' | cat -v
or letting the resulting program use a file for input.
Use another means of input
Most programs that work on input with line strings NUL
strings (xargs
, cut
, ...) typically have a -z
flag. This is primarily used when dealing with paths as a character may contain ANY character EXCEPT NUL
.
Programs like find
and git ls-files
support outputting this format, usually in the form of a -print0
or -0
flag.
Programs like sed
, tr
, bash
et. al. use special escape characters like \0
, \x0
, \x00
to generate NUL
bytes.
Massage the input
OP originally seems to have wanted to know how to use cut
with a NUL
delimiter. The problem is typically that something is separated using \n
, where \n
is a valid part of the values and not a line-separator (typically in paths).
Say you have a situation where you group files, each separated by a NUL
character, and the groups separated by \n
.
# Temporary mock output with NUL columns and newline rows
printf 'foo\0bar\nbar\0\nFOO\0BAR\0\n' > /tmp/$$.output
A work-around is to get creative with a combination of sed
, awk
or tr
to massage the output to something that suits our input/commands.
our.sed
#!/usr/bin/sed -nf
# beginning
:x
# match \0\n
/\x0$/ {
# Change \0\n to \n
s|\x0$|\n|g
# print
p
# delete
d
}
# match \n with no leading \0
/[^\x0]$/ {
# change \0 to \1
s|\x0|\x1|g
# read next line
N
# branch to beginning
bx
}
In this scenario we map:
\0\n
=> \n
\0
not followed by \n
=> \1
While a valid character in a filename, it's unlikely to pose a problem.
# Change NUL to another unlikely to be used control character
sed -f our.sed /tmp/$$.output |\
cut -d $'\x1' -f 2
output
bar
BAR