A file:
a
b
run command
dd if=file count=1 skip=0 bs=1 # show a
dd if=file count=1 skip=1 bs=1 # show "newline"
dd if=file count=1 skip=2 bs=1 # show b
I want to search the offset of the first "newline" before a given offset, with 'if' statement in a bash script (which is a dummy way):
para1=$1
while(1)
do
c=$(dd if=file count=1 bs=1 skip=$para1)
if [ $c -eq "\n" ] # How to write this line?
then
break
fi
para1=`expo $para - 1`
done
echo $para1
bash fun.sh 2
# the output should be 1
Actually I have found a solution here: How do i compare if my variable holds a newline character in shell Script
if [ ${#str} -eq 0 ]
But I wonder is it robust enough, or is there more elegant way to do it?
Please focus on the code:
c=$(dd if=test1 skip=2 bs=1 count=1)
The Command Substitution section of man bash
describes:
Bash performs the expansion by executing command... with any trailing newlines deleted.
Because of this the newline in the result of dd
command above is removed. You'll see it by the test code below:
for (( i=1; i<=3; i++ )); do
c="$(dd if=test1 skip="$i" bs=1 count=1 2>/dev/null)"
echo "skip = $i"
echo -n "$c" | xxd
done
In general bash
is not suitable for explicitly dealing with the newline character because bash sometimes automatically removes or adds it.
If perl
is your option, please try the following:
perl -0777 -ne '
$given = 3; # an example of the given offset
printf "character at offset %d = %s\n", $given, substr($_, $given, 1);
$pos = rindex(substr($_, 0, $given), "\n", $given);
if ($pos < 0) {
print "not found\n";
} else {
printf "newline found at offset %d\n", $given - $pos - 1;
}
' file
If you prefer bash
, here is the alternative in bash:
file="./file"
given=3 # an example of the given offset
str="$(xxd -ps "$file" | tr -d '\n')" # to the hexadecimal expression
for (( i=given; i>=0; i-- )); do
j=$(( i * 2 ))
c="${str:$j:2}" # substring offset j, length 2
if [[ $c = "0a" ]]; then # search for the substring "0a"
printf "newline found at offset %d\n" $(( given - i - 1 ))
exit
fi
done
echo "not found"
The concept is same as the perl version. It first converts the whole file into the hexadecimal expression and searches for the substring "0a" starting at the given position backwards.
Hope this helps.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.