LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 12-09-2007, 01:35 AM   #1
craigjward
LQ Newbie
 
Registered: Nov 2007
Posts: 24

Rep: Reputation: 15
Detect length of line in file


Hello,
I am writing a script, and I want to detect the amount of characters of each line in a file, is there a command I can use to do this?
 
Old 12-09-2007, 02:01 AM   #2
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,697
Blog Entries: 5

Rep: Reputation: 244Reputation: 244Reputation: 244
hint: man wc. There's option to count characters.
how to count for each line in file : use loops , while or for
 
Old 12-09-2007, 01:46 PM   #3
gnashley
Amigo developer
 
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,928

Rep: Reputation: 613Reputation: 613Reputation: 613Reputation: 613Reputation: 613Reputation: 613
If you are using 'read' to get each line, then you could get the line -length internally:
Code:
cat file | while read LINE ; do
THISLINE=$LINE
no_of_chars=${#THISLINE}
echo "This line has $no_of_chars characters"
done
Actually, you don't have to be using read, but this is an easy way to separate each line into a variable value.
In fact you can do the whole thing in BASH without using any external programs at all. Here's the full code for a mostly complete implementation of wc is pure shell. The real meat that you need is fairly short, but this code includes line, word and character counting:
Code:
#!/bin/bash
# copyright 2007 Gilbert Ashley <amigo@ibiblio.org>
# BashTrix wc is an implementation of the 'wc' command
# written in pure shell. Most wc options are supported.
VERSION=0.2

# show program usage
show_usage() {
echo
echo "Usage: ${0##/*} [OPTION]... [FILE]..."
echo "${0##/} -[m|w|l|L] FILE"
echo "  or: (cat|echo) | ${0##/*} [OPTION]... "
echo "Print newline, word, and byte counts for each FILE"
echo "and a total line if more than one FILE is specified."
# echo "With no FILE, or when FILE is - read standard input." #conflicts
echo "  -m, --chars            print the character counts"
echo "  -l, --lines            print the newline counts"
echo "  -L, --max-line-length  print the length of the longest line"
echo "  -w, --words            print the word counts"
echo "      --help     display this help and exit"
echo "      --version  output version information and exit"
exit
}
show_version() {
echo ${0##/*}" (BashTrix) $VERSION"
echo "Copyright 2007 Gilbert Ashley <amigo@ibiblio.org>"
echo "This is free software written in pure POSIX shell."
exit
}

# Minimum number of arguments needed by this program
MINARGS=1
# show usage if '-h' or  '--help' is the first argument or no argument is given
case $1 in
	""|"-h"|"--help") show_usage ;;
	"--version") show_version ;;
esac
# get the number of command-line arguments given
ARGC=$#
# check to make sure enough arguments were given or exit
if [[ $ARGC -lt $MINARGS ]] ; then
 echo "Too few arguments given (Minimum:$MINARGS)"
 echo
 show_usage
fi

for WORD in "$@" ; do
	case $WORD in
		-*)  true ;
			case $WORD in
				-m) COUNT_CHARS=1 ; shift ;;
				-w) COUNT_WORDS=1 ; shift ;;
				-l) COUNT_LINES=1 ; shift ;;
				-L) MAX_LINE_LENGTH=1 ; shift ;;
				--help) show_usage ;;
				--version) show_version ;;
				# -) READ_STDIN=1 ; shift ;;
				-*) echo "Unrecognized argument" ; show_usage ;;
			esac
		;;
	esac
done

# function _freq counts the number of matches
# of PATTERN in PARSESTRING and returns FREQ
# example usage: _freq $PATTERN $PARSESTRING
function _freq() { FREQ=0
! [[ $PATTERN ]] && PATTERN=$1
! [[ $PARSESTRING ]] && PARSESTRING=$2
while [[ $PARSESTRING != "" ]] ; do
	case $PARSESTRING in
		*$PATTERN*) (( FREQ++ )) ;
			PARSESTRING=${PARSESTRING#*${PATTERN}} ;;
		*) PARSESTRING="" ;;
	esac
done
echo $FREQ
}

# convert tabs to spaces
function uniform_white() {
while read GAGA ; do
 echo $GAGA
done
}

# function _line_word_count counts the words in a line
function _line_word_count() { LINE_WORD_COUNT=0
# turn all TABS into single spaces
STRING=$(echo $1 | uniform_white)
# strip off leading spaces
SEP=" "
while [[ ${STRING:0:1} = $SEP ]] ; do
 STRING=${STRING:1}
done
# strip trailing spaces
OFFSET=$(( ${#STRING} - 1 ))
while [[ ${STRING:$OFFSET:1} = $SEP ]] ; do
 # remove one CHAR from the STRING
 STRING=${STRING:0:$OFFSET}
 # decrement the OFFSET by one for the removed character
 (( OFFSET-- ))
done
PARSESTRING=$STRING
# count the number of spaces
_freq " " $PARSESTRING 1> /dev/null
# the number of words is spaces +1 except for blank lines
if [[ "$STRING" != "" ]] ; then
 LINE_WORD_COUNT=$(( $FREQ + 1 ))
fi
}

# function _line_char_count counts the characters in a line UNUSED
function _line_char_count() { LINE_CHAR_COUNT=0
#PARSESTRING=$(echo $1 | uniform_white)
PARSESTRING="$1"
while [[ $PARSESTRING != "" ]] ; do
	# read one character
	FC=${PARSESTRING:0:1}
	# advance the poiter one character
	PARSESTRING=${PARSESTRING:1}
	(( LINE_CHAR_COUNT++ ))
done
# add an extra character for the end of line CHAR
(( LINE_CHAR_COUNT++ ))
}

if [[ $# -gt 0 ]] ; then
	FILE_COUNT=0
	TOTAL_LINE_COUNT=0
	TOTAL_WORD_COUNT=0
	TOTAL_CHAR_COUNT=0
	TOTAL_LONGEST_LINE=0
	while [[ $# -gt 0 ]] ; do
		# count number of input files
		(( FILE_COUNT++ ))
		FILE_NAME="$1"
		if [ ! -r "$1" ] ; then
			echo "Cannot find file $1" 1>&2
			exit 1
		else
			FILE_LINE_COUNT=0
			FILE_WORD_COUNT=0
			FILE_CHAR_COUNT=0
			FILE_LONGEST_LINE=0
			LINE=
			IFS=
			while read LINE ; do
			  # add the curent line to the line counter
			  (( FILE_LINE_COUNT++ ))
			  # capture the text of the line
			  STRING="$LINE"
			  # count the words in this line
			  if [[ $COUNT_WORDS ]] ; then
			    _line_word_count $STRING
			    FILE_WORD_COUNT=$(( $FILE_WORD_COUNT + $LINE_WORD_COUNT ))
			  fi
			  # count the characters in this line
			  if [[ $COUNT_CHARS ]] ; then
			    LINE_CHAR_COUNT=$(( ${#LINE} + 1 ))
			    FILE_CHAR_COUNT=$(( $FILE_CHAR_COUNT + $LINE_CHAR_COUNT ))
			  fi
			  if [[ $MAX_LINE_LENGTH ]] ; then
				LINE_CHAR_COUNT=$(( ${#LINE} ))
				if [[ $LINE_CHAR_COUNT -gt $FILE_LONGEST_LINE ]] ; then
					FILE_LONGEST_LINE=$LINE_CHAR_COUNT
				fi
			  fi
			# go to next LINE
			done <"$1"
			TOTAL_LINE_COUNT=$((TOTAL_LINE_COUNT + $FILE_LINE_COUNT))
			TOTAL_WORD_COUNT=$(( $TOTAL_WORD_COUNT + $FILE_WORD_COUNT ))
			TOTAL_CHAR_COUNT=$(( $TOTAL_CHAR_COUNT + $FILE_CHAR_COUNT ))
		fi
		
		if [[ $FILE_LONGEST_LINE -gt  $TOTAL_LONGEST_LINE ]] ; then
				TOTAL_LONGEST_LINE=$FILE_LONGEST_LINE
		fi
		
		FILE_OUTPUT="$(echo $FILE_LINE_COUNT $FILE_WORD_COUNT $FILE_CHAR_COUNT \
				$FILE_LONGEST_LINE $FILE_NAME | uniform_white)"
		echo $FILE_OUTPUT
	# go to next FILE in $@
	shift
	done
	
	# detect multiple input files so the totals can be shown
	if [[ $FILE_COUNT -gt 1 ]] ; then
	 TOTAL_OUTPUT="$(echo $TOTAL_LINE_COUNT $TOTAL_WORD_COUNT $TOTAL_CHAR_COUNT \
			$TOTAL_LONGEST_LINE total | uniform_white)"
	 echo $TOTAL_OUTPUT
	fi
	exit
else
	# accept piped-in input only if "$@" is empty  ( $#=0 )
	# elif [[ $READ_STDIN ]] would enforce the POSIX
	# piped input is presumed to be separated into lines already
	FILE_LINE_COUNT=0
	FILE_WORD_COUNT=0
	FILE_CHAR_COUNT=0
	FILE_LONGEST_LINE=0
	IFS=
	while read LINE ; do
		# capture the text of the line
		STRING="$LINE"
		#increment the line counter
		(( FILE_LINE_COUNT++ ))
		# count hte words in a line
		if [[ $COUNT_WORDS ]] ; then
			_line_word_count $STRING
			TOTAL_WORD_COUNT=$(( $TOTAL_WORD_COUNT + $LINE_WORD_COUNT ))
		fi
		# count the characters in a line
		if [[ $COUNT_CHARS ]] ; then
			LINE_CHAR_COUNT=$(( ${#LINE} +1 ))
			TOTAL_CHAR_COUNT=$(( $TOTAL_CHAR_COUNT + $LINE_CHAR_COUNT ))
		fi
		# find the length of the longest line
		if [[ $MAX_LINE_LENGTH ]] ; then
			LINE_CHAR_COUNT=$(( ${#LINE} ))
			if [[ $LINE_CHAR_COUNT -gt $FILE_LONGEST_LINE ]] ; then
				FILE_LONGEST_LINE=$LINE_CHAR_COUNT
			fi
		fi
		# go to the next LINE
		shift
	done
	TOTAL_LINE_COUNT=$((TOTAL_LINE_COUNT + $FILE_LINE_COUNT))
	TOTAL_WORD_COUNT=$(( $TOTAL_WORD_COUNT + $FILE_WORD_COUNT ))
	TOTAL_CHAR_COUNT=$(( $TOTAL_CHAR_COUNT + $FILE_CHAR_COUNT ))
	TOTAL_LONGEST_LINE=$FILE_LONGEST_LINE
	SHOW_TOTALS=1
	shift
	# printf "%-5s %-20s %s\n" "hello" "you" there
	TOTAL_OUTPUT="$(echo $TOTAL_LINE_COUNT $TOTAL_WORD_COUNT $TOTAL_CHAR_COUNT \
			$TOTAL_LONGEST_LINE total | uniform_white)"
	TOTAL_OUTPUT="$(printf "%s %-2s %-2s %-2s %s\n" $TOTAL_LINE_COUNT $TOTAL_WORD_COUNT \
		$TOTAL_CHAR_COUNT $TOTAL_LONGEST_LINE total)"
	
	echo $TOTAL_OUTPUT
	exit
fi

exit $ERROR
 
Old 12-09-2007, 03:28 PM   #4
craigjward
LQ Newbie
 
Registered: Nov 2007
Posts: 24

Original Poster
Rep: Reputation: 15
Thanks,

Essentially, I am making a sliding puzzle type game in terminal using an ascii art file. I am trying to check the length of each line in the file, to make sure that the file has the right dimensions... this is as far as i have gotten. Later I will need to take the length of each line and divide it by 3 as well as divide the number of lines by 3 so that I have 9 panels to work with. In my code so far, it seems as if I am getting stuck in my loop.. can anyone tell me where my problem is?

here is my code so far...

Code:
#!/bin/bash

CURRENTLINE=
CURRENTLINELENGTH=0
MAXLINELENGTH=0
PUZZLEFILE=


echo "Craig Ward's Puzzle Game"
echo "------------------------"

if [ $# -gt 1 ]; then
	echo "Usage: puzzle [filepath]"
	exit 1
elif [ $# -eq 1 ]; then
	echo "Checking Puzzle File $1"
	MAXLINELENGTH= wc -L $1

	for i in wc -l $1; do
		CURRENTLINE= sed -n '$ip' $1
		CURRENTLINELENGHTH= wc -m $CURRENTLINE
		if [ $CURRENTLINELENGTH -lt $MAXLINELENGTH ]; then
			echo "Puzzle File Corrupt. Ending Script."
			exit 1
		fi
	done
	PUZZLEFILE= $1

elif [ $# -lt 1 ]; then
	echo "No puzzle file specified. Using default puzzle"
fi
Thanks again
 
Old 12-09-2007, 08:32 PM   #5
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,415

Rep: Reputation: 2785Reputation: 2785Reputation: 2785Reputation: 2785Reputation: 2785Reputation: 2785Reputation: 2785Reputation: 2785Reputation: 2785Reputation: 2785Reputation: 2785
Use either of these techniques to assign cmd results to a variable
var=$(wc -l $1)
or
var=`wc -l $1`
Also, you don't seem to be assigning to $ip
 
Old 12-10-2007, 03:29 AM   #6
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,808

Rep: Reputation: 2097Reputation: 2097Reputation: 2097Reputation: 2097Reputation: 2097Reputation: 2097Reputation: 2097Reputation: 2097Reputation: 2097Reputation: 2097Reputation: 2097
You have a few problems in your code. I suggest you test out code fragments at the command line to see how it works:
Code:
$ MAXLINELENGTH= wc -L sample-file 
22 sample-file
$ echo $MAXLINELENGTH

$ MAXLINELENGTH=wc -L sample-file
bash: -L: command not found
$ MAXLINELENGTH=$(wc -L sample-file)
$ echo $MAXLINELENGTH
22 sample-file
$ MAXLINELENGTH=$(wc -L <sample-file)
$ echo $MAXLINELENGTH
22
I think you wanted i to go from 1 to the number of lines in the file, however the form of for loop you used iterates over the list of words after the in keyword.
Code:
$ for i in wc -l sample-file; do echo $i; done
wc
-l
sample-file
$ for ((i=1; "$i" <= 5; i++)); do echo $i; done
1
2
3
4
5
lastly instead of
Code:
CURRENTLINE= sed -n '$ip' $1
you want
Code:
CURRENTLINE=$(sed -n "${i}p" $1)
Note the double quotes, single quotes will prevent variables from being substituted, the ${} syntax is needed to prevent the shell from looking for a variable called ip.

After you've figured that out, see if you can rewrite the loop with the read function, it will be easier to understand (and probably more efficient). Useful resource: http://tldp.org/LDP/abs/html/
 
Old 12-10-2007, 05:00 AM   #7
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,516

Rep: Reputation: 239Reputation: 239Reputation: 239
Quote:
can anyone tell me where my problem is?
yes - trying to do something this complex in shell script


maybe you should make your functions a bit smaller?

a function does one thing only and should be around about 30 lines of code.
 
Old 12-10-2007, 10:37 AM   #8
craigjward
LQ Newbie
 
Registered: Nov 2007
Posts: 24

Original Poster
Rep: Reputation: 15
Thanks a bunch!
I'm well on my way now!
 
Old 12-10-2007, 11:07 AM   #9
craigjward
LQ Newbie
 
Registered: Nov 2007
Posts: 24

Original Poster
Rep: Reputation: 15
I'm sorry for being so frusterating.. but how would I break a line in to three equal parts and cat them in to three separate files?

also, how would i go abouts randomizing the order of a sequence of numbers from 1-9?
 
Old 12-12-2007, 12:13 AM   #10
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 79
Quote:
Originally Posted by craigjward View Post
how would I break a line in to three equal parts and cat them in to three separate files?
The following will result in the three files foo0, foo1, and foo2.
Code:
#!/bin/bash

PREFIX=foo # The prefix of the resulting files

read LINE

no_chars=$((${#LINE}+1)) # The initial number of characters, including newline
total=$((no_chars + 2 * no_chars % 3)) # Up to the next multiple of 3
bytes=$((total/3)) # Bytes per file

echo "$LINE" | split "-b$bytes" -da1 - $PREFIX
Quote:
Originally Posted by craigjward View Post
how would i go abouts randomizing the order of a sequence of numbers from 1-9?
Code:
#!/bin/bash

for ((i = 1; i <=9; i++)); do
	printf "${RANDOM}\t${i}\n"
done | sort | cut -f2
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
C++ text file line by line/each line to string/array Dimitris Programming 15 03-11-2008 09:22 AM
php - Read file line by line and change a specific line. anrea Programming 2 01-28-2007 02:43 PM
POSIX - max line length? lowpro2k3 Programming 1 08-24-2005 09:59 PM
Command line tool to print length of mp3 files? J_Szucs Linux - Software 3 05-04-2004 06:01 AM
Command to list line length of multiple scripts Tekime Linux - General 2 09-06-2002 02:04 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:26 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration