#!/bin/sh
#] 
#] *********************
#] $ bash "$d_strings"'strings.sh'  - just a mish-mash dummy file with general format for bash scripts
# www.BillHowell.ca  14Oct2021 initial (should have done long ago!) 
# view in text editor, using constant-width font (eg courier), tabWidth = 3


# Read-Eval-Print Loop (REPL) is typically running in a terminal in workspace 3
# backup this file:	REPL$ sudo pinn_arcArch   "$d_strings"'strings.sh'
# backup workspace: REPL$ sudo pinnL_arcArch  "$d_start"'pgm_bash [fileops, strings] testWrkSpc REPL pLst.txt'
#************************
# List of operators, generated with :
# $ grep  "^#]"  "$d_strings"'strings.sh' |  sed "s/^#\]/# /"  >"$d_strings"'strings.sh'' TblOfCont.txt'
#  *********************


#************************
# Setup 

source  "$d_bin"'standard header.sh'  
source  "$d_strings"'strings header.sh'


#] +-----+
#] ToDos
#	19Nov2025 pinnL_pSedExpL_get_pStrL: use tac (reverse of cat) to reverse whole file!
#		before calling str_sedStr_get_pLinkL???




#*************

#] str_reverse									#(str) reverse-order str

	str_reverse()
{
	echo  "$1"  |  rev 
}  

#] str_get_length								#() number of characters (number of bytes with -c)
# https://stackoverflow.com/questions/17368067/length-of-string-in-bash
# Asked 11 years, 9 months ago
# Modified 1 year, 2 months ago
# Viewed 759k times
# UTF-8 string length
# by using wc, you could (from man bc):
#        -c, --bytes
#               print the byte counts
#        -m, --chars
#               print the character counts
# 
# edited Feb 17, 2024 at 8:08
# answered Jun 23, 2015 at 17:50
# F. Hauri - Give Up GitHub
# >> lots of good extra stuff!


	str_get_length()
{
	# echo -n doesn't echo return char
	echo  -n  "$1"  |  wc  --chars  
}


#] str_get_subStr								#() 
# https://stackoverflow.com/questions/428109/extract-substring-in-bash
# Extract substring in Bash
# Asked 16 years, 3 months ago
# Modified 1 year, 10 months ago
# Viewed 2.0m times
# >> way too many things...


	str_nChrStt_nChrEnd_get_subStr()
{
	echo  "$1"  |  cut -c  "$2"-"$3"
}

# 17Apr2025 tests
		#tst # shows line: 'C5b)  Check a few reference details, and if they are legitimate (using a quick web search and personal familiarity with references)? '
		#tst # line='C5b)  Check a few reference details, and if they are legitimate (using a quick web search and personal familiarity with references)? ';  echo "$line"					
		#tst # linLen= 133
		#tst linLen=$( echo  -n  "$line"  |  wc  --chars  );  echo  "linLen= $linLen"
		#tst # null string?
		#tst echo  "$line"  |  cut -c  65-"$linLen"
#	(using a quick web search and personal familiarity with references)? 
		#tst # shows line: 'C5b)  Check a few reference details, and '	
		#tst line='C5b)  Check a few reference details, and '; echo "$line"	
		#tst # lineLen = 41
		#tst linLen=$( echo  -n  "$line"  |  wc  --chars  ); echo  "linLen= $linLen"
		#tst # cut to 24 chr
		#tst if [ "$linLen"  -ge  65 ]; then  echo  "$line"  |  cut -c  1-65;  echo  "$line"  |  cut -c  65-"$linLen";  else  echo  "$line";  fi


#*************
#] +-----+
#] date - functions return string [date_ymd, date_ddmmmyyyy, date_ymdhm]
#]    see 'fileops.sh' to [get, change, put] file dates
# https://stackoverflow.com/questions/54066437/date-month-in-bash-without-leading-0-or-space
# BUT - 0 date option (pad with zeros) doesn't work in LMDE?  
#    eg date_ymdhms=$(date +"%0y%0m%0d %0kh%0Mm%0Ss")

# no zero-padding
#	date_ymd=$(date +%y%m%d)
#	date_ymdhm=$(date +"%y%m%d %kh%Mm")
#	date_ymdhms=$(date +"%y%m%d %kh%Mm%Ss")
#	date_ddmmmyyyy=$(date +%e%b%Y)						# %B - full name of month
#	date_ddmmmyyyy_hm=$(date +"%e%b%Y %kh%Mm")
#	date_ddmmmyyyy_hms=$(date +"%e%b%Y %kh%Mm%Ss")
		#tst dateTimeFormats_echoNoZero

#] get_UnixSec1970 							#() standard Unix timecode

	get_UnixSec1970()  
{  unixSec1970=$( date  --utc  +%s  )
	echo  "$unixSec1970"
} 


#zero-padding - try again (had feared an error was caused by this)
#] date expressions [date_ymd[, hm[s]], ddmmmyyyy[,_hm[s]], copy-paste expression into [cmdLin, script] :
# %0B - full name of month
# date_ymd=$(date +%0y%0m%0d);                          echo  "date_ymd          = $date_ymd"
# date_ymdhm=$(date +"%0y%0m%0d %0kh%0Mm");             echo  "date_ymdhm        = $date_ymdhm"
# date_ymdhms=$(date +"%0y%0m%0d %0kh%0Mm%0Ss");        echo  "date_ymdhms       = $date_ymdhms"
# date_ddmmmyyyy=$(date +%0e%0b%0Y);                    echo  "date_ddmmmyyyy    = $date_ddmmmyyyy"
# date_ddmmmyyyy_hm=$(date +"%0e%0b%0Y %0kh%0Mm");      echo  "date_ddmmmyyyy_hm = $date_ddmmmyyyy_hm"
# date_ddmmmyyyy_hms=$(date +"%0e%0b%0Y %0kh%0Mm%0Ss"); echo  "date_ddmmmyyyy_hms= $date_ddmmmyyyy_hms"
# date_hmdmy=$(date +%0kh%0Mm" "%0e%0b%0y);             echo  "date_hmdmy        = $date_hmdmy"
		#tst dateTimeFormats_echoZeroPad


#] tUnixRef_weekDaySameWeek_get_ddmmmyyyy 	#() get "weekDay" ddmmmyyyy for week of UnixSec1970
# 14Nov2025 initial
# $ man date
# SYNOPSIS
#        date [OPTION]... [+FORMAT]
#        date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]
#        %a     locale's abbreviated weekday name (e.g., Sun)
# day    	 		 		* 24 * 60 =    1,440 min * 60 s/min = 86,400 sec


	tUnixRef_weekDaySameWeek_get_ddmmmyyyy()
{
	tUnxRef="$1"
	tUnxWkDy=$( date -d  '@'"$1" +%a  )
	if    [ "$tUnxWkDy"  ==  'Sun' ]; then tDelSunday=0  
	elif  [ "$tUnxWkDy"  ==  'Mon' ]; then tDelSunday=$( calc "1*86400" )  
	elif  [ "$tUnxWkDy"  ==  'Tue' ]; then tDelSunday=$( calc "2*86400" )  
	elif  [ "$tUnxWkDy"  ==  'Wed' ]; then tDelSunday=$( calc "3*86400" ) 
	elif  [ "$tUnxWkDy"  ==  'Thu' ]; then tDelSunday=$( calc "4*86400" )  
	elif  [ "$tUnxWkDy"  ==  'Fri' ]; then tDelSunday=$( calc "5*86400" )  
	elif  [ "$tUnxWkDy"  ==  'Sat' ]; then tDelSunday=$( calc "6*86400" )  
	fi
	let "tUnixSundayOfWeek = $1 - $tDelSunday" 

	weekDay="$2"
	if    [ "$weekDay"   ==  'Sun' ]; then tDelSunday=0;  
	elif  [ "$weekDay"   ==  'Mon' ]; then tDelSunday=$( calc "1*86400" )  
	elif  [ "$weekDay"   ==  'Tue' ]; then tDelSunday=$( calc "2*86400" )  
	elif  [ "$weekDay"   ==  'Wed' ]; then tDelSunday=$( calc "3*86400" ) 
	elif  [ "$weekDay"   ==  'Thu' ]; then tDelSunday=$( calc "4*86400" )  
	elif  [ "$weekDay"   ==  'Fri' ]; then tDelSunday=$( calc "5*86400" )  
	elif  [ "$weekDay"   ==  'Sat' ]; then tDelSunday=$( calc "6*86400" )  
	fi
	let "tUnixWeekDay = $tUnixSundayOfWeek + $tDelSunday" 
	ddmmmyyyy=$( timeUnix_to_ddmmmyyyy  "$tUnixWeekDay"  )
	echo  "$ddmmmyyyy"
}

# 14Nov2025 quick test
#	10h40m 14Nov25 REPL$ sudo date -d  '@'"1763141807" +%a 
#	Fri



#] statDate_to_timeUnix						#() convert to linux stat format to timeUnix
# from "$d_web"'CompLangs/PineScript/PuetzUWS IntlStkIdxs multi-fractals.txt'
# 02Sep2023 initial 

	statDate_to_timeUnix()
{  
	year=$( echo  "$1"  |  cut --bytes=1,2,3,4 )
	mnth=$( echo  "$1"  |  cut --bytes=6,7     )
	dayy=$( echo  "$1"  |  cut --bytes=9,10    )
	hour=$( echo  "$1"  |  cut --bytes=12,13   )
	mint=$( echo  "$1"  |  cut --bytes=15,16   )
	scnd=$( echo  "$1"  |  cut --bytes=18,19   )

	date -d  "$year-$mnth-$dayy $hour:$mint:$scnd -0600" +%s 
}


#] yymmddhms_to_timeUnix					#() convert to linux stat format, then $ date -d "$timeStat" +%s
#]    note only works from 01Jan2000-present
# from "$d_web"'CompLangs/PineScript/PuetzUWS IntlStkIdxs multi-fractals.txt'
# 02Sep2023 initial 

	yymmddhms_to_timeUnix()
{  
	year=$( echo  "$1"  |  cut --bytes=1,2   )
	mnth=$( echo  "$1"  |  cut --bytes=3,4   )
	dayy=$( echo  "$1"  |  cut --bytes=5,6   )
	hour=$( echo  "$1"  |  cut --bytes=8,9   )
	mint=$( echo  "$1"  |  cut --bytes=11,12 )
	scnd=$( echo  "$1"  |  cut --bytes=14,15 )

	date -d  "20$year-$mnth-$dayy $hour:$mint:$scnd -0600" +%s 
}


#] timeUnix_to_ddmmmyyyy					#() res ipsa loquitor
#]    note only works from 01Jan2000-present
# 07Nov2025 initial, from yymmddhms_to_timeUnix
# date :
#	%d     day of month (e.g., 01)
#	%b     locale's abbreviated month name (e.g., Jan)
#	%Y     year
# search 'Linux bash convert universal time code to human readable'
# https://unix.stackexchange.com/questions/2987/how-do-i-convert-an-epoch-timestamp-to-a-human-readable-format-on-the-cli
#	How do I convert an epoch timestamp to a human readable format on the cli?
#	Asked 15 years, 1 month ago
#	Modified 2 years, 2 months ago
#	Viewed 499k times
#	
#	+--+
#	...
#	On Linux (specifically, with GNU coreutils ≥5.3):
#		date -d @1234567890
#	edited Apr 12, 2016 at 20:24
#	ngreen
#	answered Oct 11, 2010 at 18:11
#	Gilles 'SO- stop being evil'
#	
#	+--+
#	Custom format with GNU date:
#		date -d @1234567890 +'%Y-%m-%d %H:%M:%S'
#	Or with GNU awk:
#		awk 'BEGIN { print strftime("%Y-%m-%d %H:%M:%S", 1234567890); }'
#	Linked SO question: https://stackoverflow.com/questions/3249827/convert-from-unixtime-at-command-line
#	
#	edited May 23, 2017 at 12:39
#	CommunityBot
#	answered Aug 23, 2013 at 3:02
#	Ivan Chau


	timeUnix_to_ddmmmyyyy()
{  
	date -d  '@'"$1" +%d%b%Y
}

# 07Nov2025 quick test
#	10:39  7Nov2025$ date -d  '1762498800'  +%d%b%Y 
#	date: invalid date ‘1762498800’
#	~
#	10:42  7Nov2025$ date -d  '1762498800' 
#	date: invalid date ‘1762498800’
#	~
#	10:44  7Nov2025$ date -u  '1762498800' 
#	date: invalid date ‘1762498800’
#	~
#	10:48  7Nov2025$ date --utc  '1762498800' 
#	date: invalid date ‘1762498800’
#	
#	10:56  7Nov2025$ date -d @1234567890 +'%d%b%Y'
#	13Feb2009
#	>> bingo, but I need the `@
#	
#	11:00  7Nov2025$ date -d @'1762498800' +%d%b%Y
#	07Nov2025
#	>> wrong! gives today's date
#	
#	timeUnix='1762498800'
#	date -d @"$timeUnix" +%d%b%Y
#	11:00  7Nov2025$ timeUnix='1762498800'
#	~
#	11:02  7Nov2025$ date -d @"$timeUnix" +%d%b%Y
#	07Nov2025
#	>> wrong
#	~
#	11:03  7Nov2025$ timeUnix='1234567890'
#	~
#	11:04  7Nov2025$ date -d @"$timeUnix" +%d%b%Y
#	13Feb2009
#	seems OK?
#	~


#] timeUnix_to_ddmmmyyyy					#() res ipsa loquitor

	timeUnix_to_yyyymmmdd()
{
	date -d  '@'"$1" +%Y%b%d
}

# 07Nov2025 quick test
#	11:06  7Nov2025$ date -d @"$timeUnix" +%Y%b%d
#	2009Feb13
#	>> OK
#	11:46  7Nov2025$ date -d  @'1762498800' +%Y%b%d
#	2025Nov07
#	>> OK



#] tPthP_get_tDeltaDays						#() returns days between file modified dates 
# 12Oct2023 initial based on yymmddhhmmP_to_tDeltaUnix

	tPthP_get_tDeltaDays()  
{
	pinn1="$1"
	pinn2="$2"

	t1=$( pinn_timeModTo_timeUnix  "$pinn1" )
	t2=$( pinn_timeModTo_timeUnix  "$pinn2" )
	tDelta=$(( $t2 - $t1 ))
	#	echo "Unix msecs: t1 = $t1;  t2 = $t2;  tDelta (ms) = $tDelta"  
	calc  $tDelta/86400
}  


# 10:04$ echo $(( 1 * 1440 ))
# 1440
# ~
# 10:07$ echo $(( 1 / 1440 ))
# 0


#] yymmddhhmmP_to_tDeltaUnix				#() returns the number of minutes between dates in YYMMDD_HM format
# 14Oct2021 initial 
# example : see cp_Dell64_incremental_to_dated() in "$d_bin""backup.sh"  
# months are assumed to have 30.4375 days, so quite the errr for some month cross-overs

	yymmddhhmmP_to_tDeltaUnix()  
{	
	# date_ymdhm_start="$1"
	strtY=$( echo "$1"  |  sed 's/^\(.\{2\}\).*/\1/' )  
	strtM=$( echo "$1"  |  sed 's/^.\{2\}\(.\{2\}\).*/\1/' )  
	strtD=$( echo "$1"  |  sed 's/^.\{4\}\(.\{2\}\).*/\1/' )  
	strth=$( echo "$1"  |  sed 's/^.\{7\}\(.\{2\}\).*/\1/' )  
	strtm=$( echo "$1"  |  sed 's/^.\{10\}\(.\{2\}\).*/\1/' )  

	# date_ymdhm_end="$2"
	enddY=$( echo "$2"  |  sed 's/^\(.\{2\}\).*/\1/' )  
	enddM=$( echo "$2"  |  sed 's/^.\{2\}\(.\{2\}\).*/\1/' )  
	enddD=$( echo "$2"  |  sed 's/^.\{4\}\(.\{2\}\).*/\1/' )  
	enddh=$( echo "$2"  |  sed 's/^.\{7\}\(.\{2\}\).*/\1/' )  
	enddm=$( echo "$2"  |  sed 's/^.\{10\}\(.\{2\}\).*/\1/' )  

	echo  $((  \
				+ $(( $(( enddY - strtY )) * 525960 )) \
				+ $(( $(( enddM - strtM )) *  43830 )) \
				+ $(( $(( enddD - strtD )) *   1440 )) \
				+ $(( $(( enddh - strth )) *     60 )) \
				+ $(( $(( enddm - strtm ))				)) \
			 ))   
}  

# minutes/ time_unit -> mulplicands for various common time units 
# year 	* 12 * 30.4375 * 24 * 60 =  525,960
# month		  * 30.4375 * 24 * 60 =   43,830
# day    	 		 		* 24 * 60 =    1,440
# hour   						  * 60 =  		60



#] mmddYYY_to_ddmmmYYY						#() convert mm/dd/YYYY to dd-MMM-YYYY   (just use QNial!?!)
# 09Nov2022 initial 
#	mm_monthTo_mmm()
#{	pinn="$1"
#	posnStrt="$1"
#		while read -u 9 line; do
#			let "residual = residual - line"
#			echo  "residual=  $residual" 
#		done 
#}  


#08********08
#] +-----+
#] [human, code] forms of text, sed conversion between 
#]    Hum =human         : human-readable, non-encoded format 
#]    Cde =code          : safe for sed expressions like "s|$strOld|$strNew|g"
#]    Apo =apostrophe '  : special "quote-enclosed" case, as apo can't be apo-enclosed
#]    Quo =quotation  "  : special "apostophe-enclosed" case, 
#]                         not used much here as almost all sed expressions are apo-enclosed
# www.BillHowell.ca 03Aug2023 initial
# ! will be problem [my experience, some blogs]

# table of chr conversions:  see sedChrL_legend in "$d_strings"'strings header.sh' 

	sedHumToCde='s#[&]#za@z#g;s#\"#zdqz#g;s#\,#zc@z#g;s#\.#zp@z#g;s#\*#zs@z#g;s#\/#zfsz#g;s#[\]#zbsz#g;s#\$#zd@z#g;s#\^#zu@z#g;s#[(]#zrlz#g;s#[)]#zrrz#g;s#\[#zslz#g;s#\]#zsrz#g;s#\-#zm@z#g;s#[{]#zclz#g;s#\}#zcrz#g;s#[|]#zv@z#g'

	sedCdeToHum='s#za@z#\&#g;s#zdqz#\"#g;s#zc@z#\,#g;s#zp@z#\.#g;s#zs@z#\*#g;s#zfsz#\/#g;s#zbsz#\\#g;s#zd@z#\$#g;s#zu@z#\^#g;s#zrlz#\(#g;s#zrrz#\)#g;s#zslz#\[#g;s#zsrz#\]#g;s#zm@z#\-#g;s#zclz#\{#g;s#zcrz#\}#g;s#zv@z#\|#g'

	sedApoToCde="s#'#zsqz#g"  		# 04Sep2023 tried "s#\'#zsqz#g" got extra apo in reults
												# 	  went back to  "s#'#zsqz#g"
	sedCdeToApo="s#zsqz#'#g"  
	#sedQuoToCde='s#\"#zdqz#g'			# already in both lists above, here for reminder?
												# rare use probably...

# 10Oct2023 see povr_strP_replace() : 
#	#  this test skips pStrP files with [empty, comment] lines?  awesome if so, I doubt it
#		bolTabInStr=$( echo  "$strP____448"  |  sed  's|\x9|ztbz|'  |  grep  'ztbz' )
#		#	echo  "bolTabInStr = $bolTabInStr"
#	if  [[  -n "$bolTabInStr"  ]]; then 


#] strHum_sed_strCde							#() convert str format [human -> code] 

	strHum_sed_strCde()  
{  
	echo  "$1"  |  sed  "$sedHumToCde"  |  sed  "$sedApoToCde"  
}  


#] strCde_sed_strHum							#() convert str format [code -> human]  

	strCde_sed_strHum()  
{  
	echo  "$1"  |  sed  "$sedCdeToHum"  |  sed  "$sedCdeToApo"  
}  


#] str_strP_replace							#() escape str[Old, New] then replace strOld with strNew in apo str
#]    str[, P] are escaped if bolChrCd == 1, returns same format as input
# 31Jul2023 initial

	str_strP_replace()
{  
	local bolChrCd="$1" 
	local bolPStPE="$2" 
	local str_____="$3"
	local strP____="$4"

	if [ 1 -eq "$bolChrCd" ]; then
		str_____=$( strHum_sed_strCde  "$str_____" )
		strP____=$( strHum_sed_strCde  "$strP____" )
	fi
	#	echo  "str_____ = $str_____"

	local strOld=$( echo  "$strP____"  |  sed  's#\x9.*##' )
	local strNew=$( echo  "$strP____"  |  sed  's#.*\x9##' )
	str_____=$( echo  "$str_____"  |  sed  "s#$strOld#$strNew#" )
	#	echo  "strOld = $strOld"
	#	echo  "strNew = $strNew"

	if [ 1 -eq "$bolChrCd" ]; then
		str_____=$( strCde_sed_strHum  "$str_____" )
	fi
	echo  "$str_____" 
}


#08********08
#] +-----+
#] str search-replace using sed, tests: see "$d_bin"'0_test/strings/strings test.sh'


# 08********08
#] +-----+
#] [str, pinn]_[rm, get, ?sed?]Between stuff -  


#] str_chrP_rmBetween						#(str chrP) rm chrs between chr[start, end] = chrP, chrP example '{}'
#]    handy when sed is greedy and can't get result without recursion 
#]    'fileops.sh': povr_chrP_rmBetween, but doesn't work yet
# this func does NOT recurse, intentionally as that is normally useless?
# 01Feb2024 initial 

	str_chrP_rmBetween() 
{  
	strInn="$1"
	#	echo  "strInn = $strInn" 
	chrBeg=$( echo  "$2"  |  cut -c 1 )
	chrEnd=$( echo  "$2"  |  cut -c 2 )
	#	echo "chrBeg =  $chrBeg  ,chrEnd = $chrEnd"
	#nChr=${#strInn}		# maybe causes "Segmentation fault" errors in script, OK command line?
	#nChr="${#strInn}"
	nChr=5
		echo "nChr   =  $nChr"

	strOut=''
	nChrBeg=0
	posn=1
	while  [[ "$posn"  -le  "$nChr" ]];  do 
		chrNow=$(  echo  "$strInn"  |  cut -c  "$posn"  )
		#	echo  "chrNow = $chrNow"
		if		[ "$chrNow"  == "$chrEnd" ];	then let "nChrBeg=--nChrBeg"		# no action if between chrP
			if	[ "$nChrBeg" -lt 0 ];			then nChrBeg=0;  fi
		#	echo "nChrBeg   =   $nChrBeg"
		elif	[ "$chrNow"  == "$chrBeg" ];	then let "nChrBeg=++nChrBeg"		# no action if start between chrP
		#	echo "nChrBeg   =   $nChrBeg"
		fi
		
		if		[ "$nChrBeg" -eq  0 ];			then 
			if [ "$chrNow"  ==  "$chrEnd" ];	then 
				echo '5'  
			else
				strOut="$strOut$chrNow"
			fi
		#	echo "strOut = $strOut"
		fi
		let "posn= ++posn"
	done
	#	echo  "posn   =  $posn"
	#	echo  "strOut =  $strOut"
	echo  "$strOut"
}

		#tst str_chrP_rmBetween  'hard on'  '{}'
		#tst str_chrP_rmBetween  'ha{rd }on'  '{}'
		#tst str_chrP_rmBetween  'Let 1 ≤ q ≤ + ∞ {\displaystyle 1\leq q\leq +\infty } be a positive extended real quantity. Let j {\displaystyle j} and m {\displaystyle m} be non-negative integers such that j < m {\displaystyle j<m}. Furthermore, let 1 ≤ r ≤ + ∞ {\displaystyle 1\leq r\leq +\infty } be a positive extended real quantity, p ≥ 1 {\displaystyle p\geq 1} be real and θ ∈ [ 0 , 1 ] {\displaystyle \theta \in [0,1]} such that the relations'  '{}'
		#tst str_chrP_rmBetween  '{\displaystyle {\dfrac {1}{p}}={\dfrac {j}{n}}+\theta \left({\dfrac {1}{r}}-{\dfrac {m}{n}}\right)+{\dfrac {1-\theta }{q}},\qquad {\dfrac {j}{m}}\leq \theta \leq 1}'  '{}'
		#tst str_chrP_rmBetween  'for any u ∈ L q ( R n ) {\displaystyle u\in L^{q}(\mathbb {R} ^{n})} such that D m u ∈ L r ( R n ) {\displaystyle D^{m}u\in L^{r}(\mathbb {R} ^{n})}, with two exceptional cases:'    '{}'


# 08********08
#] +-----+
#] str funcs for special formats 


#] str_get_width								$(strInn) 

	str_get_width()
{
	nChr=$( echo  "$strInn"  |  wc --chars )
	echo  "$nChr"
}

# 16May2025 test
		#tst # 6
		#tst echo  'hello'  |  wc --chars
		#tst # 91
		#tst echo  'colWid_strInn_get_strOut   #(colWid strInn) pad strInn with ending spaces to reach colWid'  |  wc --chars



#] colWid_chr_strInn_get_strOut			#(colWid CHR strInn) pad strInn with ending spaces to reach colWid 
# 16May2025 initial
# https://www.howtogeek.com/815778/bash-for-loops-examples/
# >> great for loop examples

	colWid_chr_strInn_get_strOut()
{
	colWid="$1"
	chrInn="$2"
	strInn="$3"
	nStrChr=$( str_get_width  "$strInn" ) 
	let  "nSpaces =  $colWid - $nStrChr"
	strOut="$strInn"
	for (( i=1; i<=$nSpaces; i++ ))
	do  
		strOut="$strOut$chrInn"
	done
		#echo  "str= $str"
	echo  "$strOut"
}


#] strInn_get_strSed					#(strInn) strInn to sedSearch-compatible strSedCtl (Ctrl = Control chars)
#]    format: resSed=$( strInn_get_strSed "$strOrg" )  don't echo
#]    subset of chrSedCtrl= '",*.[]{}-|/  won't do ^$&\ for now
# do NOT use g for finding all cases!?!?!?
# limited use - specific to pths for now 14May2025
# 14May2025? initial
# 15May2025 doesn't work: strSed=$( echo  "$strSed" |  sed "s|\']|\\'|"  ).  must use "s|[']|[']|"
# 16May2025 I keep forgetting the g (find all occurrences) for sedExpr like s|\"|\\"|g

	strInn_get_strSed()
{
	local  strInn="$1"
	local  strSed=$( echo  "$strInn"  |  sed 's|[/]|[/]|g;s|\"|\\"|g;s|\,|\\,|g;s|\[-\]|[-]|g;s|[*]|[*]|g;s|[{]|[{]|g;s|[}]|[}]|g;s#[|]#[|]#;s|\.|\\.|g;s|[]]||g;s|[[]||g' )
	strSed=$( echo  "$strSed" |  sed "s|[']|[']|g"  )
	echo  "$strSed"
}

# 16May2025 mostly works: 
#	 's|[/]|[/]|;s|\"|\\"|;s|\,|\\,|;s|\-|\\-|;s|[*]|[*]|;s|[{]|[{]|;s|[}]|[}]|;s#[|]#[|]#;s|\.|\\.|;s|[]]||;s|[[]||'
# but / doesn't work, and I haven't figured out \ yet which was originally in strOrg


#] strSedCtrl_get_strOrigin				#(strOrigin) recover safe original str, used especially for tests
#]    subset of chrSedCtrl= ^$\&'",*.[]{}-\|/  won't do ^$&\ for now
#]    depends on apo-enclosed strings with '"'"' to incorporate apos
# DO use g for finding all cases!?!?!?
# 16May2025 initial

	strSedCtrl_get_strOrigin()
{
	local  strOrigin="$1"
	strOrigin=$( echo  "$strOrigin"  |  sed 's|\[/\]|/|g;s|\\"|"|g;s|\\,|,|g;s|\\.|.|g;s|\[-\]|-|g;s|\[{\]|{|g;s|\[}\]|}|g;s|[*]|*|g;s#\[|\]#|#;s|[[]||g;s|[]]||g' )
	strOrigin=$( echo  "$strOrigin"  |  sed "s|\['\]|'|g" )
	echo  "$strOrigin"
}

# 16May2025 mostly works: 's|\\"|"|;s|\\,|,|;s|\\.|.|;s|\\-|-|;s|\[{\]|{|;s|\[}\]|}|;s|[*]|*|;s#\[|\]#|#;s|\\[|[|;s|\\]|]|'
# s|\/|/|;


#] str_strP_get_pStrL							#(strInn, sed[Strt, Endd], pStrL)  
#]    get multiple sedStr per line in strInn -> pLinkL
#]    one must REVERSE [str, sed[Strt, Endd]] because: 
#]       the sequential cutting of strInn is based on "greedy sed", which finds the last occurence
#]       sedStart [<A HREF=", <IMG SRC="] is [unique, clean]
#]       sedEndd [", ">] is NOT unique, and gives mixed up results  (eg <IMG SREC="..."  width="110" etc)
# note: sed expressions don't have all instances. eg `g in  sed -i  "s|\(.*\)$sedStrtRev.*|\1|g"
# 06Oct2023 see "$d_bin/0_test/fileops"''
# 04Oct2023 initial, 06Oct2023 revamp 
# 15Nov2025 revamped to be [robust, efficient, clear]
# 22Nov2025 code is BROKEN, must [revamp, test]!!

	str_strP_get_pStrL()
{  
		str="$1"
	  strP="$2"
	 pStrL="$3"
	
	strInnnRev=$( echo  "$1"  |  rev )
	sedStrtRev=$( echo  "$2"  |  sed  's|\(.*\):Q:.*|\1|g'  |  rev )
	sedEnddRev=$( echo  "$2"  |  sed  's|.*:Q:\(.*\)|\1|g'  |  rev )
	#		becho  "strInnnRev= $strInnnRev"
	#		becho  "sedStrtRev= $sedStrtRev"
	#		becho  "sedEnddRev= $sedEnddRev"

	local nSedStr=$( echo  "$strInnnRev"  |  sed  "s|\($sedStrtRev\)|\1\x0|gi"  |  tr  \\0  \\n  |  grep -i  "$sedStrtRev"   | wc -l ) 
			becho  "sedStrt= $1   nSedStrt=  $nSedStr"
	if ! [ "$nSedStr" -le  '0' ]; then
		for (( nItr=0; nItr <  $nSedStr663; nItr++ )); do 
			strNoEnder=$( echo  "$strInnnRev"  |  sed  "s|\(.*\)$sedStrtRev.*|\1|i" )
			strLinkOne=$( echo  "$strNoEnder"  |  sed  "s|.*$sedEnddRev\(.*\)|\1|i" )
			strInnnRev=$( echo  "$strInnnRev"  |  sed  "s|\(.*\)$sedEnddRev.*|\1|i" )
		#	becho  "strNoEnder= $strNoEnder"
		#	becho  "strLinkOne= $strLinkOne"
		#	becho  "strInnnRev= $strInnnRev"
			becho  "$strLinkOne"  
		done
	fi
}


#] pStrPL_rev									#(pStrPL) creates reversed pStrPL (each str reversed, not line)

	pStrPL_rev()
{
		pStrPL="$1"
	pStrPLrev="$2"
	local	sedStrtRev=$( echo  "$pStrPL"  |  sed 's|\(.*\):Q:.*|\1|'  |  rev )
	local	sedEnddRev=$( echo  "$pStrPL"  |  sed 's|\(.*\):Q:.*|\1|'  |  rev )
	echo  "$sedStrtRev:Q:$sedEnddRev"  >"$pStrPLrev"
}


#] strRev_sedStrtRev_sedEnddRev_get_pStrLrev	#(see args) append multiple sedStr per line
#     args [str, sed[Strt, Endd]] must be reversed strings
#     does NOT chrCde problematic sedChrs ^$\&'",*.[]{}-\|/  - will fail with these
# the sequential cutting of strInn is based on "greedy sed", which finds the last occurence
# 		but it is typically sedStrt that is "unique", so str is reversed
# 		sedStart [<A HREF=", <IMG SRC="] is [unique, clean]
# 		sedEndd [", ">] is NOT unique, and gives mixed up results  (eg <IMG SREC="..."  width="110" etc)
# note: sed expressions don't have all instances. eg `g in  sed -i  "s|\(.*\)$sedStrtRev.*|\1|g"
# 06Oct2023 see "$d_bin/0_test/fileops"''
# 04Oct2023 initial, 06Oct2023 revamp 
# 15Nov2025 revamped to be [robust, efficient, clear]
# 19Nov2025 fileops.sh -> pinnL_pSedExpL_get_pStrL: use tac (reverse of cat) to reverse whole file!
# 08Dec2025 NYET works OK: needs OR[error, null] output if nItr > 0
# 16Dec2025 careful with links, eg <A HREF=":Q:" (:Q: is a separator, not part of [start, endd] of link)
#		do NOT end with "> - as there are often [color, woidth, etc] specs that follow the actual link.
#		also, the start can vary too.

	strRev_sedStrtRev_sedEnddRev_get_pStrLrev()
{  
	local		 strRev="$1"
	local	sedStrtRev="$2"
	local	sedEnddRev="$3"
	local	  pStrLrev="$4"

	local nSedStr=$( echo  "$strRev"  |  sed  "s|\($sedStrtRev\)|\1\x0|gi"  |  tr  \\0  \\n  |  grep -i  "$sedStrtRev"   | wc -l ) 
	#	echo  "nSedStr=  $nSedStr"				#  sedStrtRev= $sedStrtRev  sedEnddRev= $sedEnddRev"
	if ! [ "$nSedStr" -le  '0' ]; then
			strRevBas=$(	echo  "$strRev"		|  sed  "s|\(.*\)$sedStrtRev.*|\1|i" )
		for (( nItr=0; nItr <  $nSedStr; nItr++ )); do 
			strRevInn=$(	echo  "$strRevBas"	|  sed  "s|.*$sedEnddRev\(.*\)|\1|i" )
			echo  "$strRevInn"  >>"$pStrLrev"
			strRevBas=$(	echo  "$strRevBas"	|  sed  "s|\(.*\)$sedStrtRev.*|\1|i" )
		done
	fi
}


#] strRev_pStrPLrev_get_pStrLrev			#(see args) appends multiple sedStr per line
#     args [str, str[Strt, Endd]]Rev must be reversed strings
#     does NOT chrCde problematic sedChrs ^$\&'",*.[]{}-\|/  - will fail with these
# links: I currently use [HREF, SRC]= (did others in the pst)
# 07Dec2025 no overwrite of pStrRevL, which is far more useful for higher order funcs calling this
# 21Nov2025 initial, expanding str_sedStr_get_pLinkL (no longer a func) to fit pinnL_pSedRevL_get_pPthStrL

	strRev_pStrPLrev_get_pStrLrev()
{  
		strRev="$1"
	pStrPLrev="$2"
	 pStrLrev="$3"

	while IFS='' read -u 073  StrPrev; do
		StrtRev=$(	echo  "$StrPrev"  |  sed 's|\(.*\):Q:.*|\1|' )
		EnddRev=$(  echo  "$StrPrev"  |  sed 's|.*:Q:\(.*\)|\1|' )
		strRev_sedStrtRev_sedEnddRev_get_pStrLrev  "$strRev"  "$StrtRev"  "$EnddRev"  "$pStrLrev"
	done 073<"$pStrPLrev"
}


#*******************************************************************************
# Procedures -  
# This file is intended as a "source" file with functions that other bash scripts can use
# simple include the line blow in the bash that will use it
# source  "$d_strings"'strings.sh' 

	#pinn_timeModTo_pout  "$d_web"'economics, markets/Freeman 27Oct2000 The Quality Adjustment Method, How Statistical Fakery Wipes Out Inflation.html'  "$d_PROJECTS"'webHtmlOnly/economics, markets/Freeman 27Oct2000 The Quality Adjustment Method, How Statistical Fakery Wipes Out Inflation.html'



# bash "$d_strings"'strings.sh'  

# enddoc
