I have the text file with the elements of Periodic table, looking like
1 H *Name of element in 1 language* *Second l-ge* *Third* etc
2 He *Name of element in 1 language* *Second l-ge* *Third* etc
etc
(with names of the elements in different human languages)
And I need to remove all the words excluding only 1 target language, and for that I need to know how to compare STRING with array of characters (so that if none of the array letters would be matched with the comparing WORD from the textfile, this word wouldn't be printed).
Could anyone help with that?
More details / How I tried to solve this:
The first problem I encounter is that I don't know how to compare VAR with array of characters:
I wrote something like this:
#!/bin/sh
#PeriodicTable1
counter=0
while [ "$counter" -le "$#" ] ; do
counter=$(( $counter+1 )) ;
if [ "${$counter}" == *[1234567890abcdefghigklmn and etc, so here all the characters from the language that is not removing right now]* ] ; then
echo "${$counter}" ;
done
to run ./PeriodicTable1 OPTION1 OPTION2 OPT3 OPT4 etc (where options are text from the text file)\
and to get the words from text as options $1 $2 $3 etc, until $#\
and to compare them with the array of characters from language that has been chosen to be saved\
and just after (if it would work) I would use ">" to redirect output into a text file
So If the text in the file would be like this: 1 H Hydrogen Wasserstoff Hydrogène 氢 and if I would be needed to save only
Chinese, then I would typed in Terminal ./PeriodicTable1.sh 1 H Hydrogen Wasserstoff Hydrogène 氢 and would be expecting output like
this: 1 H 氢 by removing all other stuff 'cuz characters in the
words (as the options of a command) wouldn't match the Chinese
character --> wouldn't be printed
Then I wrote something like
#!/bin/sh
#PeriodicTable2
for WORD in (and here is the whole text) ; do
if [ "$WORD" == *[straight line of characters]* ; echo "$WORD" ;
done
and then
#!/bin/sh
#PeriodicTable3
counter=1 ;
save={1,2,3,4,5,6,7,8,9,0,a,b,c,d, etc} ;
while [ "$counter" -le "$#" ] ; case "${$counter}" in
*"$save"*)
echo ${$counter} ;
counter=$(( $counter+1 )) ;
;
esac
and then
#!/bin/sh
#PeriodicTable4
counter=1 ;
save={a,b, etc}
while [ "${0+$counter}" -le "$#" ] ; {
if [ "${0+$counter}" == *"$save"* ] echo "${0+$counter}" ;
counter=$(( $counter+1 )) ;
}
but nor a one of these script routines does work
and the second problem is that that if there are need to save a nonEnglish language, then letters of elements would be disappearing; but I guess that with that I could be handling, if for the first problem solution would be founded...
UPDATE:
Solution is still unfound, but I found that task already could be
done by
awk command
awk '{print $number_of_word1_in_line, $n2, $n3}'
With counting words by $var and printing only those which positions are equal to their number in line + X*n, where X is the number of words between the lines and n is var in {1..total_number_of_lines}\
With tr command
tr -c a-zA-Z '\n' < someFile.txt | sed '/^$/d'
I think you are looking for logic along the lines of what I have put together below. NOTE: I have re-formatted the input file, because it is better to have a fixed character (that would never be used in any field) as a delimiter.
As an exercise, I created my own raw table with many more languages populated (in a LibreOffice ODS file, then exported with the bars; I can provide that if you want), from which I rebuilt the modified version of your table, where I used the vertical bar (|) as the safe delimiter.
The logic was also expanded to use the first line to assign the input format values into the "cols" array, and in so doing allowing the script to adapt to the format of the input file (variations of column assignments/contents) but still output based on the specified language using --language flag.
If interested, the source of the info I extracted came from the corresponding pages identified here.
Lastly, Persian goes right-to-left, contrary to others in your table going from left-to-right. The print statement does the context-driven justification based on column position, but that info could be provided on a second header line, and parsed accordingly for output formatting.
Hope this addresses your needs!
#!/bin/sh
### QUESTION: https://stackoverflow.com/questions/74234471/linux-bash-how-to-compare-var-with-characters-pool
DBG=0
while [ $# -gt 0 ]
do
case $1 in
--language ) tLANG=$2 ; shift ; shift ;;
--debug ) DBG=1 ; shift ;;
* ) echo "\n\t Invalid option specified on the command line. Only valid: [ --language {} ] \n Bye!\n" ; exit 1 ;;
esac
done
if [ -z "${tLANG}" ] ; then echo "\n\t Language specification required on the command line. \n\n\t Usage: $0 --language [ English | Italian | Greek | Polish | French | Persian ]\n" ; exit 1 ; fi
### Format of ELEMENTS_TABLE
#Z Symbol English Italian Greek Polish French Persian
ELEMENTS_TABLE="Elements_table.csv"
### Format of ELEMENTS_RAW
#1 |2 |3___________________
#____|4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |14 |15 |16 |17 |18 ||20 |21 |22 |23
#Atomic Number|Symbol|Atomic Mass (amu, g/mol)|Latin|ALTERNATE|English|Greek|German|French|Italian|Spanish|Polish|Turkish|Russian|Afrikaans|Sesotho|Chinese|Hindi||Japanese|Hebrew|Arabic|Persian
### Position Mapping for Requestor: 1 2 6 10 7 12 9 23
#ELEMENTS_RAW="Elements_details.csv"
#awk -F \| '{
# printf("%s|%s|%s|%s|%s|%s|%s|%s|\n", $1, $2, $6, $10, $7, $12, $9, $23 ) ;
#}' < "${ELEMENTS_RAW}" >"${ELEMENTS_TABLE}"
### Match on language position
#echo $tLANG
awk -F \| -v lang="${tLANG}" -v debug="${DBG}" '\
BEGIN{
getline header ;
if( debug == 1 ){
print header ;
} ;
n=split( header, cols, "|") ;
if( debug == 1 ){
for( pos=1 ; pos <= 8 ; pos++ ){
print cols[pos] ;
} ;
} ;
#cols[1]="Z" ;
#cols[2]="Symbol" ;
#cols[3]="English" ;
#cols[4]="Italian" ;
#cols[5]="Greek" ;
#cols[6]="Polish" ;
#cols[7]="French" ;
#cols[8]="Persian" ;
lCOL=0 ;
for( pos=1 ; pos <= 8 ; pos++ ){
if( debug == 1 ){
print "cols[", pos, "] = ", cols[pos] ;
} ;
if( cols[pos] == lang ){
lCOL=pos ;
} ;
} ;
if( lCOL == 8 ){
printf("%-4s %-6s %15s\n", cols[1], cols[2], cols[lCOL] ) ;
}else{
printf("%-4s %-6s %-s\n", cols[1], cols[2], cols[lCOL] ) ;
} ;
}{
#printf("%-4s %-3s %-s %-10.7f\n", $1, $2, $lCOL, $3 ) ;
if( lCOL == 8 ){
printf("%-4s %-6s %15s\n", $1, $2, $lCOL ) ;
}else{
printf("%-4s %-6s %-s\n", $1, $2, $lCOL ) ;
} ;
}' <${ELEMENTS_TABLE}
I need to add each element of the array to the Dialog menu. The problem is that with the command $ {array [#]} the dialog is recognizing each word as an element. Look:
First attempt: Adding element with spaces
list=('Google Chrome' 'Brackets' 'Visual Studio') # my list
declare -a dia # dialog array
for index in ${!list[#]}; do # for each index in the list
dia[${#dia[#]}]=$index # add index
dia[${#dia[#]}]=${list[$index]} #add element
done
dialog --menu "MENU" 0 0 0 $(echo ${dia[#]})
# Format: dialog --menu "TITLE" 0 0 0 'Index1' 'Element1' 'Index2' 'Element2'...
# dia[0] = 0
# dia[1] = 'Google Chrome'
# dia[1] = 1
# dia[2] = 'Brackets'...
PRINT: first attempt
I did this to avoid processing each word, with the return of $ {list [#]} separating word by word, obtaining a sequence of number and string.
Second attempt: Replace ' ' with '-'
for index in ${!list[#]}; do
dgl[${#dgl[#]}]=$index
dgl[${#dgl[#]}]=${list[$index]/' '/'-'}
done
PRINT: Second attempt
What I think is happening
I believe that when passing the elements of the array to the DIALOG command it considers spaces ("Google Chrome", for example). Is there a way for me to show this with spaces?
Made all necessary changes to your code so it now works as expected.
#!/usr/bin/env bash
list=('Google Chrome' 'Brackets' 'Visual Studio') # my list
declare -a dia=() # dialog array
for index in "${!list[#]}"; do # for each index in the list
dia+=("$index" "${list[index]}")
done
choice=$(
dialog --menu "MENU" 0 0 0 "${dia[#]}" \
3>&1 1>&2 2>&3 3>&- # Swap stdout with stderr to capture returned dialog text
)
dialog_rc=$? # Save the dialog return code
clear # restore terminal background and clear
case $dialog_rc in
0)
printf 'Your choice was: %s\n' "${list[choice]}"
;;
1)
echo 'Cancelled menu'
;;
255)
echo 'Closed menu without choice'
;;
*)
printf 'Unknown return code from dialog: %d\n' $dialog_rc >&2
;;
esac
I want to delete all the elements from the combo box on click of the button in the nsis installer
nsDialogs does not have helper macros for every feature implemented by the Windows controls so sometimes you have to consult MSDN to find information about which message to send yourself.
!include nsDialogs.nsh
!include WinMessages.nsh
Page Custom MyPageCreate
Page InstFiles
Var MyComboHandle
Function ResetCombo
Pop $0
SendMessage $MyComboHandle ${CB_RESETCONTENT} 0 0
FunctionEnd
Function DeleteItemsButNotText
Pop $0
${NSD_GetText} $MyComboHandle $0
SendMessage $MyComboHandle ${CB_RESETCONTENT} 0 0
${NSD_SetText} $MyComboHandle $0
FunctionEnd
Function DeleteItemsButNotText_AlternateVersion
Pop $0
loop:
SendMessage $MyComboHandle ${CB_DELETESTRING} 0 0 $0 ; This will also clear the text if it matches the item
IntCmp $0 ${CB_ERR} "" loop loop
FunctionEnd
Function AddItems
Pop $0
${NSD_CB_AddString} $MyComboHandle "Foo"
${NSD_CB_AddString} $MyComboHandle "Bar"
SendMessage $MyComboHandle ${CB_SETCURSEL} 0 ""
FunctionEnd
Function MyPageCreate
nsDialogs::Create 1018
Pop $0
${NSD_CreateCombobox} 0 30u 100% 200u ""
Pop $MyComboHandle
Push ""
Call AddItems
${NSD_CreateButton} 0 50u 33% 12u "Reset"
Pop $0
${NSD_OnClick} $0 ResetCombo
${NSD_CreateButton} 33% 50u 33% 12u "Delete all items"
Pop $0
${NSD_OnClick} $0 DeleteItemsButNotText
${NSD_CreateButton} 66% 50u 33% 12u "Add items"
Pop $0
${NSD_OnClick} $0 AddItems
nsDialogs::Show
FunctionEnd
I want to apply onClick event on the combo box in nsis installer,so that I can execute a functionality on the click of button on combo box.
The OnClick event is not suitable for a combo-box, you want the OnChange event because the user can change it with the arrow keys etc.
To fire the change event programmatically you can call your handler directly or trick the combobox control:
!include nsDialogs.nsh
!include WinMessages.nsh
Page Custom MyPageCreate
Page InstFiles
Function OnComboChange
Pop $0
SendMessage $0 ${CB_GETCURSEL} "" "" $2
System::Call 'USER32::SendMessage(i$0,i${CB_GETLBTEXT},i$2,t.r2)'
MessageBox mb_ok "OnComboChange: $2"
FunctionEnd
Function EmulateChangeMethodA
Pop $0 ; Throw away parameter we don't care about
Push $1
Call OnComboChange
FunctionEnd
Function EmulateChangeMethodB
Pop $0 ; Throw away parameter we don't care about
FindWindow $0 "EDIT" "" $1
SendMessage $1 ${WM_COMMAND} 0x4000000 $0 ; Send WM_COMMAND,MAKELONG(0,EN_UPDATE),hwndEdit
FunctionEnd
Function EmulateChangeMethodC
Pop $0 ; Throw away parameter we don't care about
!ifndef CB_GETCOMBOBOXINFO
!define CB_GETCOMBOBOXINFO 0x0164
!endif
System::Call '*(&l4,&i16,&i16,i,i,i,i)i.r2'
SendMessage $1 ${CB_GETCOMBOBOXINFO} "" $2 ; This only works on Vista+?
System::Call '*$2(i,&i16,&i16,i,i,i,i.r0)'
System::Free $2
SendMessage $1 ${WM_COMMAND} 0x30000 $0 ; ; Send WM_COMMAND,MAKELONG(0,LBN_SELCANCEL),hwndList
FunctionEnd
Function MyPageCreate
nsDialogs::Create 1018
Pop $0
${NSD_CreateCombobox} 0 30u 100% 200u ""
Pop $1 ; This is the only control handle we care about in this example so make sure to never overwrite it!
${NSD_CB_AddString} $1 "Foo"
${NSD_CB_AddString} $1 "Bar"
SendMessage $1 ${CB_SETCURSEL} 0 ""
${NSD_OnChange} $1 OnComboChange
${NSD_CreateButton} 0 50u 33% 12u "Emulate change: A"
Pop $0
${NSD_OnClick} $0 EmulateChangeMethodA
${NSD_CreateButton} 33% 50u 33% 12u "Emulate change: B"
Pop $0
${NSD_OnClick} $0 EmulateChangeMethodB
${NSD_CreateButton} 66% 50u 33% 12u "Emulate change: C"
Pop $0
${NSD_OnClick} $0 EmulateChangeMethodC
nsDialogs::Show
FunctionEnd
what I want to do is have a page where the user browses there filesystem for a specific value, and continues on if the filename matches.
To be specific, I would like the user to locate there php executable file, and also the directory I suppose(Not sure how I would extract the directory from the full path).
You can do this with a custom page:
!include nsDialogs.nsh
!include FileFunc.nsh
Page Custom MyPageCreate MyPageLeave
Var PhpPath
Function MyPageLeave
${NSD_GetText} $PhpPath $0
${GetFileName} $0 $1
${IfNot} ${FileExists} $0
${OrIf} $1 != "php.exe"
MessageBox mb_iconstop "You must locate php.exe to continue!"
Abort
${Else}
#php path is in $0, do something with it...
${EndIf}
FunctionEnd
Function MyPageComDlgSelectPHP
Pop $0
${NSD_GetText} $PhpPath $0
nsDialogs::SelectFileDialog open $0 "php.exe|php.exe"
Pop $0
${If} $0 != ""
${NSD_SetText} $PhpPath $0
${EndIf}
FunctionEnd
Function MyPageCreate
nsDialogs::Create 1018
Pop $0
${NSD_CreateText} 0 5u -25u 13u "$ProgramFiles\PHP\php.exe"
Pop $PhpPath
${NSD_CreateBrowseButton} -23u 4u 20u 15u "..."
Pop $0
${NSD_OnClick} $0 MyPageComDlgSelectPHP
nsDialogs::Show
FunctionEnd
or you can use the directory page:
!include LogicLib.nsh
Var PhpPath
Function .onInit
StrCpy $PhpPath "$ProgramFiles\PHP" ; Default (You could probably do better by checking the registry)
FunctionEnd
PageEx Directory
DirVar $PhpPath
DirVerify leave
PageCallbacks "" PhpPageShow PhpPageLeave
DirText "Select PHP folder" "PHP Folder" "" "Select PHP folder"
PageExEnd
Function PhpPageShow
;Hide space texts
FindWindow $0 "#32770" "" $HWNDPARENT
GetDlgItem $1 $0 0x3FF
ShowWindow $1 0
GetDlgItem $1 $0 0x400
ShowWindow $1 0
FunctionEnd
Function PhpPageLeave
GetInstDirError $0
${If} $0 <> 0
${OrIfNot} ${FileExists} "$PhpPath\php.exe"
MessageBox mb_iconstop "You must locate the php folder to continue!"
Abort
${EndIf}
FunctionEnd
This can be achieved very easily with custom nsDialogs page and nsDialogs::SelectFileDialog which is designed for this purpose.
http://nsis.sourceforge.net/Docs/nsDialogs/Readme.html#ref-selectfiledialog